From 049dabbf153e56cd56b3c2830ad31f2878e5c882 Mon Sep 17 00:00:00 2001 From: Andrew Kvalheim Date: Sun, 12 Oct 2014 15:44:16 -0700 Subject: [PATCH 001/364] Use configurable content type for detection of minifiable content. Squashed changes: - Prevent side effects of content type testing. - Test for inline minification in PHP files. --- middleman-core/features/content_type.feature | 3 + middleman-core/features/minify_css.feature | 64 +++++++++++++- .../features/minify_javascript.feature | 49 ++++++++++- .../features/support/preserve_mime_types.rb | 7 ++ .../content-type-app/source/index.php | 1 + .../minify-css-app/source/inline-css.php | 8 ++ .../source/stylesheets/site.xcss.sass | 5 ++ .../minify-js-app/source/inline-js.php | 22 +++++ .../source/javascripts/js_test.xjs | 8 ++ .../middleman-core/core_extensions/request.rb | 3 + .../middleman-more/extensions/minify_css.rb | 64 ++++++++++---- .../extensions/minify_javascript.rb | 88 +++++++++++++------ 12 files changed, 276 insertions(+), 46 deletions(-) create mode 100644 middleman-core/features/support/preserve_mime_types.rb create mode 100644 middleman-core/fixtures/content-type-app/source/index.php create mode 100644 middleman-core/fixtures/minify-css-app/source/inline-css.php create mode 100755 middleman-core/fixtures/minify-css-app/source/stylesheets/site.xcss.sass create mode 100755 middleman-core/fixtures/minify-js-app/source/inline-js.php create mode 100644 middleman-core/fixtures/minify-js-app/source/javascripts/js_test.xjs diff --git a/middleman-core/features/content_type.feature b/middleman-core/features/content_type.feature index 175361d8..95aeadab 100644 --- a/middleman-core/features/content_type.feature +++ b/middleman-core/features/content_type.feature @@ -12,6 +12,8 @@ Feature: Setting the right content type for files Then the content type should be "text/css" When I go to "/README" Then the content type should be "text/plain" + When I go to "/index.php" + Then the content type should be "text/php" Scenario: Content type can be set explicitly via page or proxy or frontmatter Given a fixture app "content-type-app" @@ -31,6 +33,7 @@ Feature: Setting the right content type for files When I go to "/override.html" Then the content type should be "text/neato" + @preserve_mime_types Scenario: Content types can be overridden with mime_type Given a fixture app "content-type-app" And a file named "config.rb" with: diff --git a/middleman-core/features/minify_css.feature b/middleman-core/features/minify_css.feature index 0c707861..29c3e8c6 100644 --- a/middleman-core/features/minify_css.feature +++ b/middleman-core/features/minify_css.feature @@ -26,6 +26,18 @@ Feature: Minify CSS When I go to "/stylesheets/report.css" Then I should see "p{border:1px solid #ff6600}" + Scenario: Rendering external css in a proxied resource + Given a fixture app "minify-css-app" + And a file named "config.rb" with: + """ + activate :minify_css + proxy '/css-proxy', '/stylesheets/site.css', ignore: true + """ + And the Server is running at "minify-css-app" + When I go to "/css-proxy" + Then I should see "1" lines + And I should see "only screen and (device-width" + Scenario: Rendering external css with passthrough compressor Given a fixture app "passthrough-app" And a file named "config.rb" with: @@ -124,4 +136,54 @@ Feature: Minify CSS - """ \ No newline at end of file + """ + + Scenario: Rendering inline css in a PHP document + Given a fixture app "minify-css-app" + And a file named "config.rb" with: + """ + activate :minify_css, :inline => true + """ + And the Server is running at "minify-css-app" + When I go to "/inline-css.php" + Then I should see: + """ + + + + """ + + Scenario: Rendering inline css in a proxied resource + Given a fixture app "minify-css-app" + And a file named "config.rb" with: + """ + activate :minify_css, :inline => true + proxy '/inline-css-proxy', '/inline-css.html', ignore: true + """ + And the Server is running at "minify-css-app" + When I go to "/inline-css-proxy" + Then I should see: + """ + + """ + + @preserve_mime_types + Scenario: Configuring content types of resources to be minified + Given a fixture app "minify-css-app" + And a file named "config.rb" with: + """ + mime_type('.xcss', 'text/x-css') + activate :minify_css, content_types: ['text/x-css'], + inline: true, + inline_content_types: ['text/html'] + """ + And the Server is running at "minify-css-app" + When I go to "/stylesheets/site.xcss" + Then I should see "1" lines + And I should see "only screen and (device-width" + When I go to "/inline-css.php" + Then I should see "8" lines diff --git a/middleman-core/features/minify_javascript.feature b/middleman-core/features/minify_javascript.feature index 1fb0e699..a8235368 100644 --- a/middleman-core/features/minify_javascript.feature +++ b/middleman-core/features/minify_javascript.feature @@ -88,7 +88,7 @@ Feature: Minify Javascript """ - Scenario: Rendering inline css with a passthrough minifier using activate-style compressor + Scenario: Rendering inline JS with a passthrough minifier using activate-style compressor Given a fixture app "passthrough-app" And a file named "config.rb" with: """ @@ -148,6 +148,42 @@ Feature: Minify Javascript """ + Scenario: Rendering inline js in a PHP document + Given a fixture app "minify-js-app" + And a file named "config.rb" with: + """ + activate :minify_javascript, :inline => true + """ + And the Server is running at "minify-js-app" + When I go to "/inline-js.php" + Then I should see: + """ + + + + + + """ + + Scenario: Rendering inline js in a proxied resource + Given a fixture app "minify-js-app" + And a file named "config.rb" with: + """ + activate :minify_javascript, :inline => true + proxy '/inline-js-proxy', '/inline-js.html', ignore: true + """ + And the Server is running at "minify-js-app" + When I go to "/inline-js-proxy" + Then I should see "14" lines + Scenario: Rendering external js with the feature enabled Given a fixture app "minify-js-app" And a file named "config.rb" with: @@ -160,6 +196,17 @@ Feature: Minify Javascript When I go to "/more-js/other.js" Then I should see "1" lines + Scenario: Rendering external js in a proxied resource + Given a fixture app "minify-js-app" + And a file named "config.rb" with: + """ + activate :minify_javascript + proxy '/js-proxy', '/javascripts/js_test.js', ignore: true + """ + And the Server is running at "minify-js-app" + When I go to "/js-proxy" + Then I should see "1" lines + Scenario: Rendering external js with a passthrough minifier And the Server is running at "passthrough-app" When I go to "/javascripts/js_test.js" diff --git a/middleman-core/features/support/preserve_mime_types.rb b/middleman-core/features/support/preserve_mime_types.rb new file mode 100644 index 00000000..a791e49c --- /dev/null +++ b/middleman-core/features/support/preserve_mime_types.rb @@ -0,0 +1,7 @@ +Around('@preserve_mime_types') do |_scenario, block| + mime_types = ::Rack::Mime::MIME_TYPES.clone + + block.call + + ::Rack::Mime::MIME_TYPES.replace mime_types +end diff --git a/middleman-core/fixtures/content-type-app/source/index.php b/middleman-core/fixtures/content-type-app/source/index.php new file mode 100644 index 00000000..eb55fa96 --- /dev/null +++ b/middleman-core/fixtures/content-type-app/source/index.php @@ -0,0 +1 @@ + diff --git a/middleman-core/fixtures/minify-css-app/source/inline-css.php b/middleman-core/fixtures/minify-css-app/source/inline-css.php new file mode 100644 index 00000000..d978aafd --- /dev/null +++ b/middleman-core/fixtures/minify-css-app/source/inline-css.php @@ -0,0 +1,8 @@ + + + diff --git a/middleman-core/fixtures/minify-css-app/source/stylesheets/site.xcss.sass b/middleman-core/fixtures/minify-css-app/source/stylesheets/site.xcss.sass new file mode 100755 index 00000000..0cf9e7da --- /dev/null +++ b/middleman-core/fixtures/minify-css-app/source/stylesheets/site.xcss.sass @@ -0,0 +1,5 @@ +@import "compass/reset" + +@media handheld, only screen and (device-width: 768px) + body + display: block \ No newline at end of file diff --git a/middleman-core/fixtures/minify-js-app/source/inline-js.php b/middleman-core/fixtures/minify-js-app/source/inline-js.php new file mode 100755 index 00000000..4a7fd303 --- /dev/null +++ b/middleman-core/fixtures/minify-js-app/source/inline-js.php @@ -0,0 +1,22 @@ + + + + + diff --git a/middleman-core/fixtures/minify-js-app/source/javascripts/js_test.xjs b/middleman-core/fixtures/minify-js-app/source/javascripts/js_test.xjs new file mode 100644 index 00000000..f6a9406c --- /dev/null +++ b/middleman-core/fixtures/minify-js-app/source/javascripts/js_test.xjs @@ -0,0 +1,8 @@ +var race; +var __slice = Array.prototype.slice; + +race = function() { + var runners, winner; + winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + return print(winner, runners); +}; diff --git a/middleman-core/lib/middleman-core/core_extensions/request.rb b/middleman-core/lib/middleman-core/core_extensions/request.rb index 612001e1..cbef8d83 100644 --- a/middleman-core/lib/middleman-core/core_extensions/request.rb +++ b/middleman-core/lib/middleman-core/core_extensions/request.rb @@ -24,6 +24,9 @@ module Middleman # Sourcemap format ::Rack::Mime::MIME_TYPES['.map'] = 'application/json; charset=utf-8' + # Create a MIME type for PHP files (for detection by extensions) + ::Rack::Mime::MIME_TYPES['.php'] = 'text/php' + app.extend ClassMethods app.extend ServerMethods diff --git a/middleman-core/lib/middleman-more/extensions/minify_css.rb b/middleman-core/lib/middleman-more/extensions/minify_css.rb index 91cbf29a..61954a66 100644 --- a/middleman-core/lib/middleman-more/extensions/minify_css.rb +++ b/middleman-core/lib/middleman-more/extensions/minify_css.rb @@ -3,6 +3,8 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension option :compressor, nil, 'Set the CSS compressor to use.' option :inline, false, 'Whether to minify CSS inline within HTML files' option :ignore, [], 'Patterns to avoid minifying' + option :content_types, %w(text/css), 'Content types of resources that contain CSS' + option :inline_content_types, %w(text/html text/php), 'Content types of resources that contain inline CSS' def initialize(app, options_hash={}, &block) super @@ -16,7 +18,9 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension # Setup Rack middleware to minify CSS app.use Rack, compressor: chosen_compressor, ignore: Array(options[:ignore]) + [/\.min\./], - inline: options[:inline] + inline: options[:inline], + content_types: options[:content_types], + inline_content_types: options[:inline_content_types] end class SassCompressor @@ -39,6 +43,8 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension @compressor = options[:compressor] @ignore = options[:ignore] @inline = options[:inline] + @content_types = options[:content_types] + @inline_content_types = options[:inline_content_types] end # Rack interface @@ -47,19 +53,18 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension def call(env) status, headers, response = @app.call(env) - if inline_html_content?(env['PATH_INFO']) - minified = ::Middleman::Util.extract_response_text(response) - minified.gsub!(INLINE_CSS_REGEX) do - $1 << @compressor.compress($2) << $3 - end + content_type = headers['Content-Type'].try(:slice, /^[^;]*/) + path = env['PATH_INFO'] + minified = if @inline && minifiable_inline?(content_type) + minify_inline(::Middleman::Util.extract_response_text(response)) + elsif minifiable?(content_type) && !ignore?(path) + minify(::Middleman::Util.extract_response_text(response)) + end + + if minified headers['Content-Length'] = ::Rack::Utils.bytesize(minified).to_s response = [minified] - elsif standalone_css_content?(env['PATH_INFO']) - minified_css = @compressor.compress(::Middleman::Util.extract_response_text(response)) - - headers['Content-Length'] = ::Rack::Utils.bytesize(minified_css).to_s - response = [minified_css] end [status, headers, response] @@ -67,12 +72,41 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension private - def inline_html_content?(path) - (path.end_with?('.html') || path.end_with?('.php')) && @inline + # Whether the path should be ignored + # @param [String] path + # @return [Boolean] + def ignore?(path) + @ignore.any? { |ignore| Middleman::Util.path_match(ignore, path) } end - def standalone_css_content?(path) - path.end_with?('.css') && @ignore.none? { |ignore| Middleman::Util.path_match(ignore, path) } + # Whether this type of content can be minified + # @param [String, nil] content_type + # @return [Boolean] + def minifiable?(content_type) + @content_types.include?(content_type) + end + + # Whether this type of content contains inline content that can be minified + # @param [String, nil] content_type + # @return [Boolean] + def minifiable_inline?(content_type) + @inline_content_types.include?(content_type) + end + + # Minify the content + # @param [String] content + # @return [String] + def minify(content) + @compressor.compress(content) + end + + # Detect and minify inline content + # @param [String] content + # @return [String] + def minify_inline(content) + content.gsub(INLINE_CSS_REGEX) do + $1 + minify($2) + $3 + end end end end diff --git a/middleman-core/lib/middleman-more/extensions/minify_javascript.rb b/middleman-core/lib/middleman-more/extensions/minify_javascript.rb index d51d864f..df020765 100644 --- a/middleman-core/lib/middleman-more/extensions/minify_javascript.rb +++ b/middleman-core/lib/middleman-more/extensions/minify_javascript.rb @@ -3,6 +3,8 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension option :compressor, nil, 'Set the JS compressor to use.' option :inline, false, 'Whether to minify JS inline within HTML files' option :ignore, [], 'Patterns to avoid minifying' + option :content_types, %w(application/javascript), 'Content types of resources that contain JS' + option :inline_content_types, %w(text/html text/php), 'Content types of resources that contain inline JS' def initialize(app, options_hash={}, &block) super @@ -16,14 +18,18 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension ::Uglifier.new end - # Setup Rack middleware to minify CSS + # Setup Rack middleware to minify JS app.use Rack, compressor: chosen_compressor, ignore: Array(options[:ignore]) + [/\.min\./], - inline: options[:inline] + inline: options[:inline], + content_types: options[:content_types], + inline_content_types: options[:inline_content_types] end # Rack middleware to look for JS and compress it class Rack + INLINE_JS_REGEX = /(]*>\s*(?:\/\/(?:(?:)|(?:\]\]>)))?\s*<\/script>)/m + # Init # @param [Class] app # @param [Hash] options @@ -32,6 +38,8 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension @compressor = options[:compressor] @ignore = options[:ignore] @inline = options[:inline] + @content_types = options[:content_types] + @inline_content_types = options[:inline_content_types] end # Rack interface @@ -40,25 +48,18 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension def call(env) status, headers, response = @app.call(env) + type = headers['Content-Type'].try(:slice, /^[^;]*/) path = env['PATH_INFO'] - begin - if @inline && (path.end_with?('.html') || path.end_with?('.php')) - uncompressed_source = ::Middleman::Util.extract_response_text(response) + minified = if @inline && minifiable_inline?(type) + minify_inline(::Middleman::Util.extract_response_text(response)) + elsif minifiable?(type) && !ignore?(path) + minify(::Middleman::Util.extract_response_text(response)) + end - minified = minify_inline_content(uncompressed_source) - - headers['Content-Length'] = ::Rack::Utils.bytesize(minified).to_s - response = [minified] - elsif path.end_with?('.js') && @ignore.none? { |ignore| Middleman::Util.path_match(ignore, path) } - uncompressed_source = ::Middleman::Util.extract_response_text(response) - minified = @compressor.compress(uncompressed_source) - - headers['Content-Length'] = ::Rack::Utils.bytesize(minified).to_s - response = [minified] - end - rescue ExecJS::ProgramError => e - warn "WARNING: Couldn't compress JavaScript in #{path}: #{e.message}" + if minified + headers['Content-Length'] = ::Rack::Utils.bytesize(minified).to_s + response = [minified] end [status, headers, response] @@ -66,19 +67,48 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension private - def minify_inline_content(uncompressed_source) - uncompressed_source.gsub(/(]*>\s*(?:\/\/(?:(?:)|(?:\]\]>)))?\s*<\/script>)/m) do |match| - first = $1 - javascript = $2 - last = $3 + # Whether the path should be ignored + # @param [String] path + # @return [Boolean] + def ignore?(path) + @ignore.any? { |ignore| Middleman::Util.path_match(ignore, path) } + end - # Only compress script tags that contain JavaScript (as opposed - # to something like jQuery templates, identified with a "text/html" - # type. - if first =~ / + + diff --git a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb index 24f01b94..b605e4ce 100644 --- a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb +++ b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb @@ -1,6 +1,7 @@ # encoding: UTF-8 -require 'rack/test' +require 'rspec/expectations' +require 'capybara/cucumber' Given /^a clean server$/ do @initialize_commands = [] @@ -57,8 +58,7 @@ Given /^the Server is running$/ do end end - app_rack = @server_inst.class.to_rack_app - @browser = ::Rack::Test::Session.new(::Rack::MockSession.new(app_rack)) + Capybara.app = @server_inst.class.to_rack_app end Given /^the Server is running at "([^\"]*)"$/ do |app_path| @@ -72,60 +72,61 @@ end When /^I go to "([^\"]*)"$/ do |url| in_current_dir do - @browser.get(URI.encode(url)) + visit(URI.encode(url).to_s) end end Then /^going to "([^\"]*)" should not raise an exception$/ do |url| in_current_dir do - expect{ @browser.get(URI.encode(url)) }.to_not raise_exception + + expect{ visit(URI.encode(url).to_s) }.to_not raise_exception end end Then /^the content type should be "([^\"]*)"$/ do |expected| in_current_dir do - expect(@browser.last_response.content_type).to start_with(expected) + expect(page.response_headers['Content-Type']).to start_with expected end end Then /^I should see "([^\"]*)"$/ do |expected| in_current_dir do - expect(@browser.last_response.body).to include(expected) + expect(page.body).to include expected end end Then /^I should see '([^\']*)'$/ do |expected| in_current_dir do - expect(@browser.last_response.body).to include(expected) + expect(page.body).to include expected end end Then /^I should see:$/ do |expected| in_current_dir do - expect(@browser.last_response.body).to include(expected) + expect(page.body).to include expected end end Then /^I should not see "([^\"]*)"$/ do |expected| in_current_dir do - expect(@browser.last_response.body).to_not include(expected) + expect(page.body).not_to include expected end end Then /^I should not see:$/ do |expected| in_current_dir do - expect(@browser.last_response.body).to_not include(expected.chomp) + expect(page.body).not_to include expected end end Then /^the status code should be "([^\"]*)"$/ do |expected| in_current_dir do - expect(@browser.last_response.status).to eq expected.to_i + expect(page.status_code).to eq expected.to_i end end Then /^I should see "([^\"]*)" lines$/ do |lines| in_current_dir do - expect(@browser.last_response.body.chomp.split($/).length).to eq(lines.to_i) + expect(page.body.chomp.split($/).length).to eq lines.to_i end end diff --git a/middleman-core/middleman-core.gemspec b/middleman-core/middleman-core.gemspec index 03e468bd..0e8e9fa7 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("hooks", ["~> 0.3"]) # Builder - s.add_dependency("rack-test", ["~> 0.6.2"]) + s.add_dependency("capybara", ["~> 2.4.4"]) # CLI s.add_dependency("thor", [">= 0.15.2", "< 2.0"]) From bb44e59e6e3e3c0675f171b14eaa755f9792abea Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 9 Jun 2015 10:15:24 -0700 Subject: [PATCH 052/364] Blindly attempt to imrpove encoding situation --- .../core_extensions/front_matter.rb | 11 ++++++++++- .../middleman-core/core_extensions/rendering.rb | 16 ++++++++++++++-- .../step_definitions/server_steps.rb | 2 -- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb index 3e1ca08b..8499a339 100644 --- a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb @@ -185,7 +185,7 @@ module Middleman::CoreExtensions # Avoid weird race condition when a file is renamed. content = begin - File.read(full_path) + read_data_file(full_path) rescue ::EOFError rescue ::IOError rescue ::Errno::ENOENT @@ -208,6 +208,15 @@ module Middleman::CoreExtensions [data, content] end + def read_data_file(path) + data = File.open(path, 'rb') { |io| io.read } + if data.respond_to?(:force_encoding) + # Set it to the default external (without verifying) + data.force_encoding(Encoding.default_external) if Encoding.default_external + end + data + end + def normalize_path(path) path.sub(%r{^#{Regexp.escape(app.source_dir)}\/}, '') end diff --git a/middleman-core/lib/middleman-core/core_extensions/rendering.rb b/middleman-core/lib/middleman-core/core_extensions/rendering.rb index 39cb4006..fb3ec6a5 100644 --- a/middleman-core/lib/middleman-core/core_extensions/rendering.rb +++ b/middleman-core/lib/middleman-core/core_extensions/rendering.rb @@ -217,10 +217,19 @@ module Middleman # Render the partial if found, otherwide throw exception _render_with_all_renderers(found_partial, locals, self, options, &block) else - File.read(found_partial) + read_template_file(found_partial) end end + def read_template_file(path) + data = ::File.open(path, 'rb') { |io| io.read } + if data.respond_to?(:force_encoding) + # Set it to the default external (without verifying) + data.force_encoding(::Encoding.default_external) if ::Encoding.default_external + end + data + end + # Partial locator. # # @param [String] partial_name @@ -277,6 +286,7 @@ module Middleman extension = File.extname(path) options = opts.dup.merge(options_for_ext(extension)) options[:outvar] ||= '@_out_buf' + options[:default_encoding] ||= 'UTF-8' options.delete(:layout) # Overwrite with frontmatter options @@ -299,6 +309,8 @@ module Middleman ::Tilt.new(path, 1, options) { body } end + ', :default_encoding => 'Big5' + # Render using Tilt content = template.render(context || ::Object.new, locs, &block) @@ -326,7 +338,7 @@ module Middleman # @param [String] path # @return [String] def template_data_for_file(path) - File.read(File.expand_path(path, source_dir)) + read_template_file(File.expand_path(path, source_dir)) end # Get a hash of configuration options for a given file extension, from diff --git a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb index b605e4ce..5f2f2886 100644 --- a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb +++ b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb @@ -1,5 +1,3 @@ -# encoding: UTF-8 - require 'rspec/expectations' require 'capybara/cucumber' From 3e46e8139fba9c9448ae83be771485a2f1768895 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 9 Jun 2015 10:17:47 -0700 Subject: [PATCH 053/364] Add osx build env --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 15a12e33..492342aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,16 +3,16 @@ bundler_args: --without development rvm: - ruby-head - 2.2 - - 2.1.1 - - 2.1.0 - - 2.0.0 + - 2.1 + - 2.0 - 1.9.3 - - jruby-19mode +os: + - linux + - osx matrix: fast_finish: true allow_failures: - rvm: ruby-head - - rvm: jruby-19mode env: TEST=true before_install: git submodule update --init --recursive script: bundle exec rake test From 6562716aa53999f681cca13496e081c7c5fe32fe Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 9 Jun 2015 10:42:41 -0700 Subject: [PATCH 054/364] bone head move --- middleman-core/lib/middleman-core/core_extensions/rendering.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/middleman-core/lib/middleman-core/core_extensions/rendering.rb b/middleman-core/lib/middleman-core/core_extensions/rendering.rb index fb3ec6a5..7bbfd7cb 100644 --- a/middleman-core/lib/middleman-core/core_extensions/rendering.rb +++ b/middleman-core/lib/middleman-core/core_extensions/rendering.rb @@ -309,8 +309,6 @@ module Middleman ::Tilt.new(path, 1, options) { body } end - ', :default_encoding => 'Big5' - # Render using Tilt content = template.render(context || ::Object.new, locs, &block) From ae2d1487fae8f5b08c5057257e4725c8ece42a2f Mon Sep 17 00:00:00 2001 From: Todd Fisher Date: Thu, 11 Jun 2015 15:24:19 -0400 Subject: [PATCH 055/364] Update util.rb line 128, Float type is also not something that can be dup'ed, similar to Fixnum and friends --- 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 8a00eb9d..7d8512f0 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -122,7 +122,7 @@ module Middleman Hamster::Set.new(res) when Hamster::Vector, Hamster::Set, Hamster::SortedSet obj.map { |element| recursively_enhance(element) } - when ::TrueClass, ::FalseClass, ::Fixnum, ::Symbol, ::NilClass + when ::TrueClass, ::FalseClass, ::Fixnum, ::Symbol, ::NilClass, ::Float obj else obj.dup.freeze From 70d4671d2c2588690de27950ba28bda49009ff6e Mon Sep 17 00:00:00 2001 From: Eliott Appleford Date: Sun, 14 Jun 2015 11:55:10 +0100 Subject: [PATCH 056/364] Allow extended globs with ignore This makes it match the default behaviour of Dir#glob --- .../lib/middleman-core/sitemap/extensions/ignores.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb index df803505..c26f8a80 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb @@ -59,7 +59,11 @@ module Middleman elsif path.is_a? String path_clean = ::Middleman::Util.normalize_path(path) if path_clean.include?('*') # It's a glob - @ignored_callbacks << proc { |p| File.fnmatch(path_clean, p) } + if defined? File::FNM_EXTGLOB + @ignored_callbacks << proc { |p| File.fnmatch(path_clean, p, File::FNM_EXTGLOB) } + else + @ignored_callbacks << proc { |p| File.fnmatch(path_clean, p) } + end else # Add a specific-path ignore unless that path is already covered return if ignored?(path_clean) From e09f7fadb5c092bf667eaf4e16d53891dc643925 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 15 Jun 2015 09:58:29 -0700 Subject: [PATCH 057/364] Add better error messaging for #1541 --- .../lib/middleman-core/core_extensions/rendering.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/middleman-core/lib/middleman-core/core_extensions/rendering.rb b/middleman-core/lib/middleman-core/core_extensions/rendering.rb index 7bbfd7cb..d1c361ee 100644 --- a/middleman-core/lib/middleman-core/core_extensions/rendering.rb +++ b/middleman-core/lib/middleman-core/core_extensions/rendering.rb @@ -428,6 +428,10 @@ module Middleman layout_path = locate_layout(layout_name, current_engine) + if !layout_path + raise ::Middleman::CoreExtensions::Rendering::TemplateNotFound, "Could not locate layout: #{layout_name}" + end + extension = File.extname(layout_path) engine = extension[1..-1].to_sym From 7383f67874ca6bdbc31fe5db70279118ea5deac3 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 16 Jun 2015 15:30:37 -0700 Subject: [PATCH 058/364] Implement yaml data postscript --- CHANGELOG.md | 3 + middleman-core/features/data.feature | 7 + .../features/front-matter-neighbor.feature | 11 -- middleman-core/features/front-matter.feature | 22 --- .../source/front-matter-line-2.html.erb | 5 +- .../source/json-front-matter-2.php.erb | 7 - .../json-front-matter-encoding.html.erb | 7 - .../source/json-front-matter-line-2.html.erb | 7 - .../source/json-front-matter.html.erb | 6 - .../frontmatter-neighbor-app/config.rb | 2 +- .../source/json-front-matter-2.php.erb | 2 - .../json-front-matter-2.php.erb.frontmatter | 4 - .../source/json-front-matter.html.erb | 1 - .../json-front-matter.html.erb.frontmatter | 4 - .../config.rb | 2 +- .../data/examples/withcontent.yaml | 11 ++ .../source/extracontent.html.haml.erb | 4 + .../lib/middleman-core/configuration.rb | 1 - .../middleman-core/core_extensions/data.rb | 8 +- .../core_extensions/front_matter.rb | 108 +------------ .../lib/middleman-core/renderers/liquid.rb | 21 ++- .../lib/middleman-core/util/data.rb | 153 ++++++++++++++++++ 22 files changed, 215 insertions(+), 181 deletions(-) delete mode 100644 middleman-core/fixtures/frontmatter-app/source/json-front-matter-2.php.erb delete mode 100644 middleman-core/fixtures/frontmatter-app/source/json-front-matter-encoding.html.erb delete mode 100644 middleman-core/fixtures/frontmatter-app/source/json-front-matter-line-2.html.erb delete mode 100644 middleman-core/fixtures/frontmatter-app/source/json-front-matter.html.erb delete mode 100644 middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter-2.php.erb delete mode 100644 middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter-2.php.erb.frontmatter delete mode 100644 middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter.html.erb delete mode 100644 middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter.html.erb.frontmatter create mode 100644 middleman-core/fixtures/nested-data-app/data/examples/withcontent.yaml create mode 100644 middleman-core/fixtures/nested-data-app/source/extracontent.html.haml.erb create mode 100644 middleman-core/lib/middleman-core/util/data.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 22202562..9ae9a891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ master === +* Removed ability to use JSON as frontmatter. Still allowed in data/ folder. +* Added YAML data postscript. Like frontmatter, but reversed. Attach content after the key/value data as a `:postscript` key to the data structure (if Hash). + # 4.0.0.beta.2 * Fixed regression causing exceptions to be silently thrown away outside of `--verbose` mode in the dev server. diff --git a/middleman-core/features/data.feature b/middleman-core/features/data.feature index fcce8445..db8bede6 100644 --- a/middleman-core/features/data.feature +++ b/middleman-core/features/data.feature @@ -51,3 +51,10 @@ Feature: Local Data API Then I should see "title1:Hello" Then I should see "title2:More" Then I should see "title3:Stuff" + + Scenario: Using data postscript + Given the Server is running at "nested-data-app" + When I go to "/extracontent.html" + Then I should see "

With Content

" + Then I should see '

Header 2

' + Then I should see "

Paragraph 1

" diff --git a/middleman-core/features/front-matter-neighbor.feature b/middleman-core/features/front-matter-neighbor.feature index 08b4f57c..e2e5cc69 100644 --- a/middleman-core/features/front-matter-neighbor.feature +++ b/middleman-core/features/front-matter-neighbor.feature @@ -30,17 +30,6 @@ Feature: Neighboring YAML Front Matter Then I should not see "---" When I go to "/front-matter-encoding.html.erb.frontmatter" Then I should see "File Not Found" - - Scenario: Rendering html (json) - Given the Server is running at "frontmatter-neighbor-app" - When I go to "/json-front-matter.html.erb.frontmatter" - Then I should see "File Not Found" - When I go to "/json-front-matter-2.php" - Then I should see "

This is the title

" - Then I should see "This is the title" Then I should not see "---" - - Scenario: Rendering html (json) - Given the Server is running at "frontmatter-app" - When I go to "/json-front-matter.html" - Then I should see "

This is the title

" - Then I should not see ";;;" - When I go to "/json-front-matter-2.php" - Then I should see "

This is the title

" - Then I should see "" - Then I should see ";;;" - - Scenario: JSON not on first line, with encoding - Given the Server is running at "frontmatter-app" - When I go to "/json-front-matter-encoding.html" - Then I should see "

This is the title

" - Then I should not see ";;;" Scenario: A template changes frontmatter during preview Given the Server is running at "frontmatter-app" diff --git a/middleman-core/fixtures/frontmatter-app/source/front-matter-line-2.html.erb b/middleman-core/fixtures/frontmatter-app/source/front-matter-line-2.html.erb index 7aeb16b9..d0c0802c 100644 --- a/middleman-core/fixtures/frontmatter-app/source/front-matter-line-2.html.erb +++ b/middleman-core/fixtures/frontmatter-app/source/front-matter-line-2.html.erb @@ -1,7 +1,10 @@

Test

+ +

<%= current_page.data.title %>

+ --- layout: false title: This is the title --- -

<%= current_page.data.title %>

+
Stuff
diff --git a/middleman-core/fixtures/frontmatter-app/source/json-front-matter-2.php.erb b/middleman-core/fixtures/frontmatter-app/source/json-front-matter-2.php.erb deleted file mode 100644 index 7208cf6f..00000000 --- a/middleman-core/fixtures/frontmatter-app/source/json-front-matter-2.php.erb +++ /dev/null @@ -1,7 +0,0 @@ -;;; - "layout": false, - "title": "This is the title" -;;; - -

<%= current_page.data.title %>

- diff --git a/middleman-core/fixtures/frontmatter-app/source/json-front-matter-encoding.html.erb b/middleman-core/fixtures/frontmatter-app/source/json-front-matter-encoding.html.erb deleted file mode 100644 index d05b1f70..00000000 --- a/middleman-core/fixtures/frontmatter-app/source/json-front-matter-encoding.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -# encoding: UTF-8 -;;; -"layout": false, -"title": "This is the title" -;;; - -

<%= current_page.data.title %>

diff --git a/middleman-core/fixtures/frontmatter-app/source/json-front-matter-line-2.html.erb b/middleman-core/fixtures/frontmatter-app/source/json-front-matter-line-2.html.erb deleted file mode 100644 index 56b65add..00000000 --- a/middleman-core/fixtures/frontmatter-app/source/json-front-matter-line-2.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -

Test

-;;; -layout: false, -title: "This is the title" -;;; - -

<%= current_page.data.title %>

diff --git a/middleman-core/fixtures/frontmatter-app/source/json-front-matter.html.erb b/middleman-core/fixtures/frontmatter-app/source/json-front-matter.html.erb deleted file mode 100644 index da001783..00000000 --- a/middleman-core/fixtures/frontmatter-app/source/json-front-matter.html.erb +++ /dev/null @@ -1,6 +0,0 @@ -;;; - "layout": false, - "title": "This is the title" -;;; - -

<%= current_page.data.title %>

diff --git a/middleman-core/fixtures/frontmatter-neighbor-app/config.rb b/middleman-core/fixtures/frontmatter-neighbor-app/config.rb index f5edde7f..babfbc2c 100644 --- a/middleman-core/fixtures/frontmatter-neighbor-app/config.rb +++ b/middleman-core/fixtures/frontmatter-neighbor-app/config.rb @@ -15,7 +15,7 @@ class NeighborFrontmatter < ::Middleman::Extension next unless file - fmdata = app.extensions[:front_matter].frontmatter_and_content(file[:full_path]).first + fmdata = ::Middleman::Util::Data.parse(file[:full_path], :yaml).first opts = fmdata.extract!(:layout, :layout_engine, :renderer_options, :directory_index, :content_type) opts[:renderer_options].symbolize_keys! if opts.key?(:renderer_options) ignored = fmdata.delete(:ignored) diff --git a/middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter-2.php.erb b/middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter-2.php.erb deleted file mode 100644 index c271a92f..00000000 --- a/middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter-2.php.erb +++ /dev/null @@ -1,2 +0,0 @@ -

<%= current_page.data.title %>

- diff --git a/middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter-2.php.erb.frontmatter b/middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter-2.php.erb.frontmatter deleted file mode 100644 index 415cefbc..00000000 --- a/middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter-2.php.erb.frontmatter +++ /dev/null @@ -1,4 +0,0 @@ -;;; - "layout": false, - "title": "This is the title" -;;; \ No newline at end of file diff --git a/middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter.html.erb b/middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter.html.erb deleted file mode 100644 index 1ae95c52..00000000 --- a/middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter.html.erb +++ /dev/null @@ -1 +0,0 @@ -

<%= current_page.data.title %>

diff --git a/middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter.html.erb.frontmatter b/middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter.html.erb.frontmatter deleted file mode 100644 index 415cefbc..00000000 --- a/middleman-core/fixtures/frontmatter-neighbor-app/source/json-front-matter.html.erb.frontmatter +++ /dev/null @@ -1,4 +0,0 @@ -;;; - "layout": false, - "title": "This is the title" -;;; \ No newline at end of file diff --git a/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb b/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb index 011d5230..1fc88608 100644 --- a/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb +++ b/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb @@ -26,7 +26,7 @@ class NeighborFrontmatter < ::Middleman::Extension end def apply_neighbor_data(resource, file) - fmdata = app.extensions[:front_matter].frontmatter_and_content(file[:full_path]).first + fmdata = ::Middleman::Util::Data.parse(file[:full_path], :yaml).first opts = fmdata.extract!(:layout, :layout_engine, :renderer_options, :directory_index, :content_type) opts[:renderer_options].symbolize_keys! if opts.key?(:renderer_options) ignored = fmdata.delete(:ignored) diff --git a/middleman-core/fixtures/nested-data-app/data/examples/withcontent.yaml b/middleman-core/fixtures/nested-data-app/data/examples/withcontent.yaml new file mode 100644 index 00000000..74d583cd --- /dev/null +++ b/middleman-core/fixtures/nested-data-app/data/examples/withcontent.yaml @@ -0,0 +1,11 @@ +--- +name: "With Content" +--- + +## Header 2 + +Paragraph 1 + +Paragraph 2 + +### Header 3 \ No newline at end of file diff --git a/middleman-core/fixtures/nested-data-app/source/extracontent.html.haml.erb b/middleman-core/fixtures/nested-data-app/source/extracontent.html.haml.erb new file mode 100644 index 00000000..90e0e6f8 --- /dev/null +++ b/middleman-core/fixtures/nested-data-app/source/extracontent.html.haml.erb @@ -0,0 +1,4 @@ +%h1= data.examples.withcontent.name + +:markdown + <%= data.examples.withcontent.postscript.gsub("\n", "\n\s\s") %> diff --git a/middleman-core/lib/middleman-core/configuration.rb b/middleman-core/lib/middleman-core/configuration.rb index e8c9b647..81422461 100644 --- a/middleman-core/lib/middleman-core/configuration.rb +++ b/middleman-core/lib/middleman-core/configuration.rb @@ -33,7 +33,6 @@ module Middleman # Set the value of a setting by key. Creates the setting if it doesn't exist. # @param [Symbol] key # @param [Object] val - # rubocop:disable UselessSetterCall def []=(key, val) setting_obj = setting(key) || define_setting(key) setting_obj.value = val diff --git a/middleman-core/lib/middleman-core/core_extensions/data.rb b/middleman-core/lib/middleman-core/core_extensions/data.rb index 205021d4..9169410a 100644 --- a/middleman-core/lib/middleman-core/core_extensions/data.rb +++ b/middleman-core/lib/middleman-core/core_extensions/data.rb @@ -1,6 +1,5 @@ -require 'yaml' -require 'active_support/json' require 'middleman-core/contracts' +require 'middleman-core/util/data' module Middleman module CoreExtensions @@ -100,9 +99,10 @@ module Middleman basename = File.basename(data_path, extension) if %w(.yaml .yml).include?(extension) - data = ::YAML.load_file(file[:full_path]) + data, postscript = ::Middleman::Util::Data.parse(file[:full_path], :yaml) + data[:postscript] = postscript if !postscript.nil? && data.is_a?(Hash) elsif extension == '.json' - data = ::ActiveSupport::JSON.decode(file[:full_path].read) + data, _postscript = ::Middleman::Util::Data.parse(file[:full_path], :json) else return end diff --git a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb index 9f672a7e..0e26259a 100644 --- a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb @@ -1,11 +1,12 @@ -require 'active_support/core_ext/hash/keys' +# Core Pathname library used for traversal require 'pathname' -# Parsing YAML frontmatter -require 'yaml' +# DbC +require 'middleman-core/contracts' -# Parsing JSON frontmatter -require 'active_support/json' +require 'active_support/core_ext/hash/keys' + +require 'middleman-core/util/data' # Extensions namespace module Middleman::CoreExtensions @@ -13,13 +14,6 @@ module Middleman::CoreExtensions # Try to run after routing but before directory_indexes self.resource_list_manipulator_priority = 90 - YAML_ERRORS = [StandardError] - - # https://github.com/tenderlove/psych/issues/23 - if defined?(Psych) && defined?(Psych::SyntaxError) - YAML_ERRORS << Psych::SyntaxError - end - def initialize(app, options_hash={}, &block) super @@ -71,7 +65,7 @@ module Middleman::CoreExtensions return [{}, nil] unless file - @cache[file[:full_path]] ||= frontmatter_and_content(file[:full_path]) + @cache[file[:full_path]] ||= ::Middleman::Util::Data.parse(file[:full_path]) end Contract ArrayOf[IsA['Middleman::SourceFile']], ArrayOf[IsA['Middleman::SourceFile']] => Any @@ -80,93 +74,5 @@ module Middleman::CoreExtensions @cache.delete(file[:full_path]) end end - - # Get the frontmatter and plain content from a file - # @param [String] path - # @return [Array] - Contract Pathname => [Hash, Maybe[String]] - def frontmatter_and_content(full_path) - data = {} - - return [data, nil] if ::Middleman::Util.binary?(full_path) - - # Avoid weird race condition when a file is renamed. - content = begin - File.read(full_path) - rescue ::EOFError - rescue ::IOError - rescue ::Errno::ENOENT - '' - end - - begin - if content =~ /\A.*coding:/ - lines = content.split(/\n/) - lines.shift - content = lines.join("\n") - end - - result = parse_yaml_front_matter(content, full_path) || parse_json_front_matter(content, full_path) - return result if result - rescue - # Probably a binary file, move on - end - - [data, content] - end - - private - - # Parse YAML frontmatter out of a string - # @param [String] content - # @return [Array] - Contract String, Pathname => Maybe[[Hash, String]] - def parse_yaml_front_matter(content, full_path) - yaml_regex = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m - if content =~ yaml_regex - content = content.sub(yaml_regex, '') - - begin - data = YAML.load($1) || {} - data = data.symbolize_keys - rescue *YAML_ERRORS => e - app.logger.error "YAML Exception parsing #{full_path}: #{e.message}" - return nil - end - else - return nil - end - - [data, content] - rescue - [{}, content] - end - - # Parse JSON frontmatter out of a string - # @param [String] content - # @return [Array] - Contract String, Pathname => Maybe[[Hash, String]] - def parse_json_front_matter(content, full_path) - json_regex = /\A(;;;\s*\n.*?\n?)^(;;;\s*$\n?)/m - - if content =~ json_regex - content = content.sub(json_regex, '') - - begin - json = ($1 + $2).sub(';;;', '{').sub(';;;', '}') - data = ::ActiveSupport::JSON.decode(json).symbolize_keys - rescue => e - app.logger.error "JSON Exception parsing #{full_path}: #{e.message}" - return nil - end - - else - return nil - end - - [data, content] - rescue - [{}, content] - end end end diff --git a/middleman-core/lib/middleman-core/renderers/liquid.rb b/middleman-core/lib/middleman-core/renderers/liquid.rb index 16817caf..e09306b4 100644 --- a/middleman-core/lib/middleman-core/renderers/liquid.rb +++ b/middleman-core/lib/middleman-core/renderers/liquid.rb @@ -27,7 +27,26 @@ module Middleman next unless resource.source_file[:relative_path].to_s =~ %r{\.liquid$} # Convert data object into a hash for liquid - resource.add_metadata locals: { data: app.extensions[:data].data_store.to_h } + resource.add_metadata locals: { + data: stringify_recursive(app.extensions[:data].data_store.to_h) + } + end + end + + def stringify_recursive(hash) + {}.tap do |h| + hash.each { |key, value| h[key.to_s] = map_value(value) } + end + end + + def map_value(thing) + case thing + when Hash + stringify_recursive(thing) + when Array + thing.map { |v| map_value(v) } + else + thing end end end diff --git a/middleman-core/lib/middleman-core/util/data.rb b/middleman-core/lib/middleman-core/util/data.rb new file mode 100644 index 00000000..1d107ef9 --- /dev/null +++ b/middleman-core/lib/middleman-core/util/data.rb @@ -0,0 +1,153 @@ +# Core Pathname library used for traversal +require 'pathname' + +# DbC +require 'middleman-core/contracts' + +# Shared util methods +require 'middleman-core/util' + +# Parsing YAML data +require 'yaml' + +# Parsing JSON data +require 'active_support/json' + +module Middleman + module Util + module Data + include Contracts + + module_function + + YAML_ERRORS = [StandardError] + + # https://github.com/tenderlove/psych/issues/23 + if defined?(Psych) && defined?(Psych::SyntaxError) + YAML_ERRORS << Psych::SyntaxError + end + + # Get the frontmatter and plain content from a file + # @param [String] path + # @return [Array] + Contract Pathname, Maybe[Symbol] => [Hash, Maybe[String]] + def parse(full_path, known_type=nil) + data = {} + + return [data, nil] if ::Middleman::Util.binary?(full_path) + + # Avoid weird race condition when a file is renamed. + content = begin + File.read(full_path) + rescue ::EOFError + rescue ::IOError + rescue ::Errno::ENOENT + '' + end + + begin + if content =~ /\A.*coding:/ + lines = content.split(/\n/) + lines.shift + content = lines.join("\n") + end + + if known_type + if known_type == :yaml + result = parse_yaml(content, full_path, true) + elsif known_type == :json + result = parse_json(content, full_path) + end + else + result = parse_yaml(content, full_path, false) + end + + return result if result + rescue + # Probably a binary file, move on + end + + [data, content] + end + + # Parse YAML frontmatter out of a string + # @param [String] content + # @return [Array] + Contract String, Pathname, Bool => Maybe[[Hash, String]] + def parse_yaml(content, full_path, require_yaml=false) + total_delims = content.scan(/^(?:---|\.\.\.)\s*(?:\n|$)/).length + has_first_line_delim = !content.match(/\A(---\s*(?:\n|$))/).nil? + # has_closing_delim = (total_delims > 1 && has_first_line_delim) || (!has_first_line_delim && total_delims == 1) + + parts = content.split(/^(?:---|\.\.\.)\s*(?:\n|$)/) + parts.shift if parts[0].empty? + + yaml_string = nil + additional_content = nil + + if require_yaml + yaml_string = parts[0] + additional_content = parts[1] + else + if total_delims > 1 + if has_first_line_delim + yaml_string = parts[0] + additional_content = parts[1] + else + additional_content = content + end + else + additional_content = parts[0] + end + end + + return [{}, additional_content] if yaml_string.nil? + + begin + data = map_value(::YAML.load(yaml_string) || {}) + rescue *YAML_ERRORS => e + $stderr.puts "YAML Exception parsing #{full_path}: #{e.message}" + return nil + end + + [data, additional_content] + rescue + [{}, additional_content] + end + + # Parse JSON frontmatter out of a string + # @param [String] content + # @return [Array] + Contract String, Pathname => Maybe[[Hash, String]] + def parse_json(content, full_path) + begin + data = map_value(::ActiveSupport::JSON.decode(content)) + rescue => e + $stderr.puts "JSON Exception parsing #{full_path}: #{e.message}" + return nil + end + + [data, nil] + rescue + [{}, nil] + end + + def symbolize_recursive(hash) + {}.tap do |h| + hash.each { |key, value| h[key.to_sym] = map_value(value) } + end + end + + def map_value(thing) + case thing + when Hash + symbolize_recursive(thing) + when Array + thing.map { |v| map_value(v) } + else + thing + end + end + end + end +end From 1efe6a27c55f92f5a1ebdf5c7889490c65bbf24a Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 16 Jun 2015 16:47:42 -0700 Subject: [PATCH 059/364] Add tests for Slim inline filters. Refactor similar feature in Haml filters. Closes #1542 --- .../markdown_kramdown_in_slim.feature | 42 ++++++++++++++++++ .../fixtures/markdown-in-slim-app/config.rb | 0 .../source/images/blank.gif | Bin 0 -> 43 bytes .../source/link_target.html.markdown | 4 ++ .../lib/middleman-core/file_renderer.rb | 8 ++-- .../lib/middleman-core/renderers/haml.rb | 28 +++++++++--- .../lib/middleman-core/renderers/kramdown.rb | 13 ++++-- .../lib/middleman-core/renderers/redcarpet.rb | 12 ++--- .../lib/middleman-core/renderers/sass.rb | 6 +-- .../lib/middleman-core/renderers/slim.rb | 28 +++++++----- 10 files changed, 107 insertions(+), 34 deletions(-) create mode 100644 middleman-core/features/markdown_kramdown_in_slim.feature create mode 100644 middleman-core/fixtures/markdown-in-slim-app/config.rb create mode 100755 middleman-core/fixtures/markdown-in-slim-app/source/images/blank.gif create mode 100755 middleman-core/fixtures/markdown-in-slim-app/source/link_target.html.markdown diff --git a/middleman-core/features/markdown_kramdown_in_slim.feature b/middleman-core/features/markdown_kramdown_in_slim.feature new file mode 100644 index 00000000..9e58a461 --- /dev/null +++ b/middleman-core/features/markdown_kramdown_in_slim.feature @@ -0,0 +1,42 @@ +Feature: Markdown support in Slim (Kramdown) + In order to test support of the Slim markdown filter + + Scenario: Markdown filter in Slim works (with Kramdown) + Given a fixture app "markdown-in-slim-app" + And a file named "config.rb" with: + """ + set :markdown_engine, :kramdown + activate :directory_indexes + """ + And a file named "source/markdown_filter.html.slim" with: + """ + markdown: + # H1 + + paragraph + """ + Given the Server is running at "markdown-in-slim-app" + When I go to "/markdown_filter/" + Then I should see ">H1" + Then I should see "

paragraph

" + + + Scenario: Markdown filter in Slim uses our link_to and image_tag helpers (with Kramdown) + Given a fixture app "markdown-in-slim-app" + And a file named "config.rb" with: + """ + set :markdown_engine, :kramdown + activate :directory_indexes + """ + And a file named "source/link_and_image.html.slim" with: + """ + markdown: + [A link](/link_target.html) + + ![image](blank.gif){: srcset="image_2x.jpg 2x"} + """ + Given the Server is running at "markdown-in-slim-app" + When I go to "/link_and_image/" + Then I should see "/link_target/" + Then I should see "/images/image_2x.jpg 2x" + Then I should see 'src="/images/blank.gif"' diff --git a/middleman-core/fixtures/markdown-in-slim-app/config.rb b/middleman-core/fixtures/markdown-in-slim-app/config.rb new file mode 100644 index 00000000..e69de29b diff --git a/middleman-core/fixtures/markdown-in-slim-app/source/images/blank.gif b/middleman-core/fixtures/markdown-in-slim-app/source/images/blank.gif new file mode 100755 index 0000000000000000000000000000000000000000..2498f1aac58dab923f0fd99b1c8ee6b8c53c7158 GIT binary patch literal 43 rcmZ?wbhEHbWMp7uXkcKtd-pB_1B2pE76uT|0TCb>1|}vKMh0sDy$1%8 literal 0 HcmV?d00001 diff --git a/middleman-core/fixtures/markdown-in-slim-app/source/link_target.html.markdown b/middleman-core/fixtures/markdown-in-slim-app/source/link_target.html.markdown new file mode 100755 index 00000000..4f970c47 --- /dev/null +++ b/middleman-core/fixtures/markdown-in-slim-app/source/link_target.html.markdown @@ -0,0 +1,4 @@ +--- +layout: false +--- +Hello World \ No newline at end of file diff --git a/middleman-core/lib/middleman-core/file_renderer.rb b/middleman-core/lib/middleman-core/file_renderer.rb index f9087004..796587d2 100644 --- a/middleman-core/lib/middleman-core/file_renderer.rb +++ b/middleman-core/lib/middleman-core/file_renderer.rb @@ -53,6 +53,7 @@ module Middleman extension = File.extname(path) options = opts.merge(options_for_ext(extension)) options[:outvar] ||= '@_out_buf' + options[:context] = context options.delete(:layout) # Overwrite with frontmatter options @@ -66,9 +67,10 @@ module Middleman end # Read compiled template from disk or cache - template = cache.fetch(:compiled_template, extension, options, body) do - ::Tilt.new(path, 1, options) { body } - end + template = ::Tilt.new(path, 1, options) { body } + # template = cache.fetch(:compiled_template, extension, options, body) do + # ::Tilt.new(path, 1, options) { body } + # end # Render using Tilt content = ::Middleman::Util.instrument 'render.tilt', path: path do diff --git a/middleman-core/lib/middleman-core/renderers/haml.rb b/middleman-core/lib/middleman-core/renderers/haml.rb index 8f98ddc6..7e2b6fbb 100644 --- a/middleman-core/lib/middleman-core/renderers/haml.rb +++ b/middleman-core/lib/middleman-core/renderers/haml.rb @@ -20,29 +20,45 @@ module Middleman # thus making it impossible to pass our Middleman instance # in. So we have to resort to heavy hackery :( class HamlTemplate < ::Tilt::HamlTemplate + def initialize(*args, &block) + super + + @context = @options[:context] if @options.key?(:context) + end + def prepare end def evaluate(scope, locals, &block) - ::Middleman::Renderers::Haml.last_haml_scope = scope - - options = @options.merge(filename: eval_file, line: line) + options = @options.merge(filename: eval_file, line: line, context: @context || scope) @engine = ::Haml::Engine.new(data, options) output = @engine.render(scope, locals, &block) - ::Middleman::Renderers::Haml.last_haml_scope = nil - output end end # Haml Renderer class Haml < ::Middleman::Extension - cattr_accessor :last_haml_scope def initialize(app, options={}, &block) super + ::Haml::Options.defaults[:context] = nil + ::Haml::Options.send :attr_accessor, :context + + [::Haml::Filters::Sass, ::Haml::Filters::Scss, ::Haml::Filters::Markdown].each do |f| + f.class_exec do + def self.render_with_options(text, compiler_options) + modified_options = options.dup + modified_options[:context] = compiler_options[:context] + + text = template_class.new(nil, 1, modified_options) {text}.render + super(text, compiler_options) + end + end + end + ::Tilt.prefer(::Middleman::Renderers::HamlTemplate, :haml) # Add haml helpers to context diff --git a/middleman-core/lib/middleman-core/renderers/kramdown.rb b/middleman-core/lib/middleman-core/renderers/kramdown.rb index c93d254d..86317560 100644 --- a/middleman-core/lib/middleman-core/renderers/kramdown.rb +++ b/middleman-core/lib/middleman-core/renderers/kramdown.rb @@ -4,10 +4,16 @@ module Middleman module Renderers # Our own Kramdown Tilt template that simply uses our custom renderer. class KramdownTemplate < ::Tilt::KramdownTemplate - def evaluate(scope, *) - @output ||= begin - MiddlemanKramdownHTML.scope = (defined?(::Middleman::Renderers::Haml) && ::Middleman::Renderers::Haml.last_haml_scope) ? ::Middleman::Renderers::Haml.last_haml_scope : scope + def initialize(*args, &block) + super + @context = @options[:context] if @options.key?(:context) + end + + def evaluate(context, *) + MiddlemanKramdownHTML.scope = @context || context + + @output ||= begin output, warnings = MiddlemanKramdownHTML.convert(@engine.root, @engine.options) @engine.warnings.concat(warnings) output @@ -38,6 +44,7 @@ module Middleman attr = el.attr.dup link = attr.delete('href') + scope.link_to(content, link, attr) end end diff --git a/middleman-core/lib/middleman-core/renderers/redcarpet.rb b/middleman-core/lib/middleman-core/renderers/redcarpet.rb index 0e141969..545a3c87 100644 --- a/middleman-core/lib/middleman-core/renderers/redcarpet.rb +++ b/middleman-core/lib/middleman-core/renderers/redcarpet.rb @@ -10,6 +10,12 @@ module Middleman escape_html: :filter_html } + def initialize(*args, &block) + super + + @context = @options[:context] if @options.key?(:context) + end + # Overwrite built-in Tilt version. # Don't overload :renderer option with smartypants # Support renderer-level options @@ -40,11 +46,7 @@ module Middleman def evaluate(scope, _) @output ||= begin - if defined?(::Middleman::Renderers::Haml) - MiddlemanRedcarpetHTML.scope = ::Middleman::Renderers::Haml.last_haml_scope || scope - else - MiddlemanRedcarpetHTML.scope = scope - end + MiddlemanRedcarpetHTML.scope = @context || scope @engine.render(data) end diff --git a/middleman-core/lib/middleman-core/renderers/sass.rb b/middleman-core/lib/middleman-core/renderers/sass.rb index f796992d..ff449f4b 100644 --- a/middleman-core/lib/middleman-core/renderers/sass.rb +++ b/middleman-core/lib/middleman-core/renderers/sass.rb @@ -94,11 +94,7 @@ module Middleman # Change Sass path, for url functions, to the build folder if we're building # @return [Hash] def sass_options - ctx = if defined?(::Middleman::Renderers::Haml) - ::Middleman::Renderers::Haml.last_haml_scope || @context - else - @context - end + ctx = @context more_opts = { load_paths: ctx.config[:sass_assets_paths], diff --git a/middleman-core/lib/middleman-core/renderers/slim.rb b/middleman-core/lib/middleman-core/renderers/slim.rb index 21277fe4..16640f4a 100644 --- a/middleman-core/lib/middleman-core/renderers/slim.rb +++ b/middleman-core/lib/middleman-core/renderers/slim.rb @@ -7,9 +7,24 @@ module SafeTemplate end end -class Slim::Template +class ::Slim::Template include SafeTemplate + def initialize(file, line, opts, &block) + if opts.key?(:context) + context_hack = { + context: opts[:context] + } + + ::Slim::Embedded::SassEngine.disable_option_validator! + %w(sass scss markdown).each do |engine| + ::Slim::Embedded.options[engine.to_sym] = context_hack + end + end + + super + end + def precompiled_preamble(locals) "__in_slim_template = true\n" << super end @@ -32,17 +47,6 @@ module Middleman disable_escape: true ) end - - def after_configuration - context_hack = { - context: app.template_context_class.new(app) - } - - ::Slim::Embedded::SassEngine.disable_option_validator! - %w(sass scss markdown).each do |engine| - ::Slim::Embedded.options[engine.to_sym] = context_hack - end - end end end end From 3fca2c6961215a2e0b9d00faee6d185c4b93a5d7 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 22 Jun 2015 10:37:17 -0700 Subject: [PATCH 060/364] Add relative argument to stylesheet and javascript helpers. Closes #1539 --- CHANGELOG.md | 1 + .../features/relative_assets.feature | 11 ++++ .../absolute_image_relative_css.html.erb | 9 ++++ .../source/javascripts/app.js | 3 ++ .../source/relative_image.html.erb | 1 + .../relative_image_absolute_css.html.erb | 9 ++++ .../core_extensions/default_helpers.rb | 50 +++++++++++++++++-- .../extensions/relative_assets.rb | 12 ++--- 8 files changed, 83 insertions(+), 13 deletions(-) create mode 100644 middleman-core/fixtures/relative-assets-app/source/absolute_image_relative_css.html.erb create mode 100644 middleman-core/fixtures/relative-assets-app/source/javascripts/app.js create mode 100644 middleman-core/fixtures/relative-assets-app/source/relative_image_absolute_css.html.erb diff --git a/CHANGELOG.md b/CHANGELOG.md index 22573947..c9378726 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ master * Empower link_to in a i18n context. * Add retina files support on automatic_image_sizes * Fix woff/woff2 confusion in asset hashing. +* Support `relative: false` on `stylesheet_link_tag` and `javascript_include_tag` 3.3.12 === diff --git a/middleman-core/features/relative_assets.feature b/middleman-core/features/relative_assets.feature index 1ebafdfa..e0c6b16f 100644 --- a/middleman-core/features/relative_assets.feature +++ b/middleman-core/features/relative_assets.feature @@ -21,6 +21,12 @@ Feature: Relative Assets Given "relative_assets" feature is "disabled" And the Server is running at "relative-assets-app" When I go to "/relative_image.html" + Then I should see '"/stylesheets/relative_assets.css"' + Then I should see '"/javascripts/app.js"' + Then I should see "/images/blank.gif" + When I go to "/absolute_image_relative_css.html" + Then I should see '"stylesheets/relative_assets.css"' + Then I should see '"javascripts/app.js"' Then I should see "/images/blank.gif" Scenario: Rendering css with the feature enabled @@ -54,6 +60,11 @@ Feature: Relative Assets Given "relative_assets" feature is "enabled" And the Server is running at "relative-assets-app" When I go to "/relative_image.html" + Then I should see '"stylesheets/relative_assets.css"' + Then I should see '"javascripts/app.js"' + When I go to "/relative_image_absolute_css.html" + Then I should see '"/stylesheets/relative_assets.css"' + Then I should see '"/javascripts/app.js"' Then I should not see "/images/blank.gif" And I should see "images/blank.gif" diff --git a/middleman-core/fixtures/relative-assets-app/source/absolute_image_relative_css.html.erb b/middleman-core/fixtures/relative-assets-app/source/absolute_image_relative_css.html.erb new file mode 100644 index 00000000..1a763ecf --- /dev/null +++ b/middleman-core/fixtures/relative-assets-app/source/absolute_image_relative_css.html.erb @@ -0,0 +1,9 @@ + + + <%= stylesheet_link_tag :relative_assets, relative: true %> + <%= javascript_include_tag :app, relative: true %> + + + <%= image_tag "blank.gif" %> + + \ No newline at end of file diff --git a/middleman-core/fixtures/relative-assets-app/source/javascripts/app.js b/middleman-core/fixtures/relative-assets-app/source/javascripts/app.js new file mode 100644 index 00000000..a9ec7a89 --- /dev/null +++ b/middleman-core/fixtures/relative-assets-app/source/javascripts/app.js @@ -0,0 +1,3 @@ +function hello() { + console.log('world'); +} \ No newline at end of file diff --git a/middleman-core/fixtures/relative-assets-app/source/relative_image.html.erb b/middleman-core/fixtures/relative-assets-app/source/relative_image.html.erb index 4fb9dc0c..4344f2a2 100644 --- a/middleman-core/fixtures/relative-assets-app/source/relative_image.html.erb +++ b/middleman-core/fixtures/relative-assets-app/source/relative_image.html.erb @@ -1,6 +1,7 @@ <%= stylesheet_link_tag :relative_assets %> + <%= javascript_include_tag :app %> <%= image_tag "blank.gif" %> diff --git a/middleman-core/fixtures/relative-assets-app/source/relative_image_absolute_css.html.erb b/middleman-core/fixtures/relative-assets-app/source/relative_image_absolute_css.html.erb new file mode 100644 index 00000000..4e910c47 --- /dev/null +++ b/middleman-core/fixtures/relative-assets-app/source/relative_image_absolute_css.html.erb @@ -0,0 +1,9 @@ + + + <%= stylesheet_link_tag :relative_assets, relative: false %> + <%= javascript_include_tag :app, relative: false %> + + + <%= image_tag "blank.gif" %> + + \ No newline at end of file diff --git a/middleman-core/lib/middleman-more/core_extensions/default_helpers.rb b/middleman-core/lib/middleman-more/core_extensions/default_helpers.rb index 0ac4c147..cbb94768 100644 --- a/middleman-core/lib/middleman-more/core_extensions/default_helpers.rb +++ b/middleman-core/lib/middleman-more/core_extensions/default_helpers.rb @@ -99,6 +99,36 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension end end + # Override helper to add `relative` opt-out. + def stylesheet_link_tag(*sources) + options = { + :rel => 'stylesheet' + }.update(sources.extract_options!.symbolize_keys) + + path_options = {} + path_options[:relative] = options.delete(:relative) if options.key?(:relative) + + sources.flatten.inject(ActiveSupport::SafeBuffer.new) do |all,source| + all << tag(:link, { + href: asset_path(:css, source, path_options) + }.update(options)) + end + end + + # Override helper to add `relative` opt-out. + def javascript_include_tag(*sources) + options = sources.extract_options!.symbolize_keys + + path_options = {} + path_options[:relative] = options.delete(:relative) if options.key?(:relative) + + sources.flatten.inject(::ActiveSupport::SafeBuffer.new) do |all,source| + all << content_tag(:script, nil, { + src: asset_path(:js, source, path_options) + }.update(options)) + end + end + # Output a stylesheet link tag based on the current path # # @param [Symbol] asset_ext The type of asset @@ -153,8 +183,9 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension # # @param [Symbol] kind The type of file # @param [String] source The path to the file + # @param [Hash] options Additional options. # @return [String] - def asset_path(kind, source) + def asset_path(kind, source, options={}) return source if source.to_s.include?('//') || source.to_s.start_with?('data:') asset_folder = case kind when :css @@ -174,29 +205,38 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension source << ".#{kind}" unless ignore_extension || source.end_with?(".#{kind}") asset_folder = '' if source.start_with?('/') # absolute path - asset_url(source, asset_folder) + asset_url(source, asset_folder, options) end # Get the URL of an asset given a type/prefix # # @param [String] path The path (such as "photo.jpg") # @param [String] prefix The type prefix (such as "images") + # @param [Hash] options Additional options. # @return [String] The fully qualified asset url - def asset_url(path, prefix='') + def asset_url(path, prefix='', options={}) # Don't touch assets which already have a full path - if path.include?('//') || path.start_with?('data:') + if path.include?('//') || path.start_with?('data:') || !current_resource path else # rewrite paths to use their destination path - if resource = sitemap.find_resource_by_destination_path(url_for(path)) + result = if resource = sitemap.find_resource_by_destination_path(url_for(path)) resource.url else path = File.join(prefix, path) + if resource = sitemap.find_resource_by_path(path) resource.url else File.join(config[:http_prefix], path) end end + + if options[:relative] != true + result + else + current_dir = Pathname('/' + current_resource.destination_path) + Pathname(result).relative_path_from(current_dir.dirname).to_s + end end end diff --git a/middleman-core/lib/middleman-more/extensions/relative_assets.rb b/middleman-core/lib/middleman-more/extensions/relative_assets.rb index 130bffb8..95eb291b 100644 --- a/middleman-core/lib/middleman-more/extensions/relative_assets.rb +++ b/middleman-core/lib/middleman-more/extensions/relative_assets.rb @@ -13,16 +13,12 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension # asset_url override for relative assets # @param [String] path # @param [String] prefix + # @param [Hash] options Additional options. # @return [String] - def asset_url(path, prefix='') - path = super(path, prefix) + def asset_url(path, prefix='', options={}) + options[:relative] = true unless options.key?(:relative) - if path.include?('//') || path.start_with?('data:') || !current_resource - path - else - current_dir = Pathname('/' + current_resource.destination_path) - Pathname(path).relative_path_from(current_dir.dirname).to_s - end + path = super(path, prefix, options) end end end From 709a0d1a6c7502da2b3e64167cbd59afec03d255 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 22 Jun 2015 10:48:40 -0700 Subject: [PATCH 061/364] Fix previous commit --- middleman-core/lib/middleman-more/extensions/asset_host.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-more/extensions/asset_host.rb b/middleman-core/lib/middleman-more/extensions/asset_host.rb index 194eaa85..c5c58ec3 100644 --- a/middleman-core/lib/middleman-more/extensions/asset_host.rb +++ b/middleman-core/lib/middleman-more/extensions/asset_host.rb @@ -32,7 +32,7 @@ class Middleman::Extensions::AssetHost < ::Middleman::Extension # @param [String] path # @param [String] prefix # @return [String] - def asset_url(path, prefix='') + def asset_url(path, prefix='', options={}) controller = extensions[:asset_host] original_output = super From 8bbda9ea7b9e3a44ab97db804de4a60e9c671288 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 22 Jun 2015 11:28:09 -0700 Subject: [PATCH 062/364] Whoops again --- middleman-core/lib/middleman-more/extensions/cache_buster.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-more/extensions/cache_buster.rb b/middleman-core/lib/middleman-more/extensions/cache_buster.rb index 20d00f9b..1028cb84 100644 --- a/middleman-core/lib/middleman-more/extensions/cache_buster.rb +++ b/middleman-core/lib/middleman-more/extensions/cache_buster.rb @@ -21,7 +21,7 @@ class Middleman::Extensions::CacheBuster < ::Middleman::Extension # asset_url override if we're using cache busting # @param [String] path # @param [String] prefix - def asset_url(path, prefix='') + def asset_url(path, prefix='', options={}) http_path = super if http_path.include?('://') || !%w(.css .png .jpg .jpeg .svg .svgz .webp .js .gif).include?(File.extname(http_path)) From 9abcdaa7f7630abeb3b4de64519391b779c620af Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 23 Jun 2015 15:49:36 -0700 Subject: [PATCH 063/364] Experiment with activersupport bump --- middleman-core/middleman-core.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/middleman-core.gemspec b/middleman-core/middleman-core.gemspec index 0e8e9fa7..12909e75 100644 --- a/middleman-core/middleman-core.gemspec +++ b/middleman-core/middleman-core.gemspec @@ -32,7 +32,7 @@ Gem::Specification.new do |s| s.add_dependency("thor", [">= 0.15.2", "< 2.0"]) # Helpers - s.add_dependency("activesupport", ["~> 4.1.0"]) + s.add_dependency("activesupport", ["~> 4.2.0"]) s.add_dependency("padrino-helpers", ["~> 0.12.3"]) # Watcher From 724e249b490d869d5b1f5aa1ef64ec316bb3f38c Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 23 Jun 2015 15:53:12 -0700 Subject: [PATCH 064/364] Experiment with activersupport bump --- middleman-core/middleman-core.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/middleman-core.gemspec b/middleman-core/middleman-core.gemspec index 12909e75..91fa76d3 100644 --- a/middleman-core/middleman-core.gemspec +++ b/middleman-core/middleman-core.gemspec @@ -32,7 +32,7 @@ Gem::Specification.new do |s| s.add_dependency("thor", [">= 0.15.2", "< 2.0"]) # Helpers - s.add_dependency("activesupport", ["~> 4.2.0"]) + s.add_dependency("activesupport", ["~> 4.1"]) s.add_dependency("padrino-helpers", ["~> 0.12.3"]) # Watcher From 232aca91bced48f77efa31b0a0ddf696a17d4cfd Mon Sep 17 00:00:00 2001 From: Max Meyer Date: Thu, 25 Jun 2015 22:26:46 +0200 Subject: [PATCH 065/364] Make testing a little bit easier and require features-directory to make subdirectories in cucumber work --- .rubocop.yml | 1 + Gemfile | 2 +- gem_rake_helper.rb | 2 +- middleman-core/.rspec | 1 + middleman-core/cucumber.yml | 2 ++ 5 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 middleman-core/.rspec create mode 100644 middleman-core/cucumber.yml diff --git a/.rubocop.yml b/.rubocop.yml index 2a518da3..68908de8 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -14,6 +14,7 @@ AllCops: - 'middleman-core/fixtures/**/*' - 'middleman-core/features/**/*' - 'middleman-core/spec/**/*' + DisplayCopNames: true LineLength: Enabled: false MethodLength: diff --git a/Gemfile b/Gemfile index f34fbaec..6ed44aac 100644 --- a/Gemfile +++ b/Gemfile @@ -9,7 +9,7 @@ gem 'pry', '~> 0.10', group: :development gem 'aruba', '~> 0.6' gem 'rspec', '~> 3.0' gem 'fivemat', '~> 1.3' -gem 'cucumber', '~> 1.3' +gem 'cucumber', '~> 2.0' # Optional middleman dependencies, included for tests gem 'less', '2.3', require: false diff --git a/gem_rake_helper.rb b/gem_rake_helper.rb index 5f95c90e..a90ea7dc 100644 --- a/gem_rake_helper.rb +++ b/gem_rake_helper.rb @@ -21,7 +21,7 @@ Cucumber::Rake::Task.new do |t| exempt_tags << '--tags ~@encoding' unless Object.const_defined?(:Encoding) exempt_tags << '--tags ~@nowindows' if Gem.win_platform? exempt_tags << '--tags ~@travishatesme' if ENV['TRAVIS'] == 'true' - t.cucumber_opts = "--color #{exempt_tags.join(' ')} --strict --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}" + t.cucumber_opts = "--require features --color #{exempt_tags.join(' ')} --strict --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}" end Cucumber::Rake::Task.new(:cucumber_wip) do |t| diff --git a/middleman-core/.rspec b/middleman-core/.rspec new file mode 100644 index 00000000..4e1e0d2f --- /dev/null +++ b/middleman-core/.rspec @@ -0,0 +1 @@ +--color diff --git a/middleman-core/cucumber.yml b/middleman-core/cucumber.yml new file mode 100644 index 00000000..a65d694e --- /dev/null +++ b/middleman-core/cucumber.yml @@ -0,0 +1,2 @@ +default: --require features --tags ~@wip +wip: --require features --tags @wip From 6aa7ce741a11db6fc25f3d10a30fb0a79095779e Mon Sep 17 00:00:00 2001 From: Max Meyer Date: Thu, 25 Jun 2015 15:39:56 +0200 Subject: [PATCH 066/364] Refactor preview server to support server_name and bind_address --- Gemfile | 3 + .../features/cli/preview_server.feature | 532 ++++++++++++++++++ .../preview-server-app/bin/dns_server.rb | 33 ++ .../config-complications.rb | 11 + .../preview-server-app/config-empty.rb | 0 .../fixtures/preview-server-app/config.rb | 11 + .../preview-server-app/source/index.html.erb | 1 + .../preview-server-app/source/layout.erb | 9 + .../source/layouts/custom.erb | 8 + .../preview-server-app/source/real.html | 1 + .../source/real/index.html.erb | 5 + .../source/should_be_ignored.html | 1 + .../source/should_be_ignored2.html | 1 + .../source/should_be_ignored3.html | 1 + .../preview-server-app/source/static.html | 1 + .../lib/middleman-core/application.rb | 6 +- .../lib/middleman-core/cli/server.rb | 12 +- .../lib/middleman-core/dns_resolver.rb | 73 +++ .../dns_resolver/basic_network_resolver.rb | 52 ++ .../dns_resolver/hosts_resolver.rb | 63 +++ .../dns_resolver/local_link_resolver.rb | 44 ++ .../dns_resolver/network_resolver.rb | 42 ++ .../lib/middleman-core/preview_server.rb | 94 ++-- .../middleman-core/preview_server/checks.rb | 81 +++ .../preview_server/information.rb | 273 +++++++++ .../network_interface_inventory.rb | 65 +++ .../preview_server/server_hostname.rb | 39 ++ .../preview_server/server_information.rb | 144 +++++ .../server_information_validator.rb | 18 + .../preview_server/server_ip_address.rb | 55 ++ .../preview_server/server_url.rb | 50 ++ .../preview_server/tcp_port_prober.rb | 29 + .../lib/middleman-core/step_definitions.rb | 1 + .../step_definitions/commandline_steps.rb | 88 +++ .../spec/middleman-core/dns_resolver_spec.rb | 118 ++++ .../preview_server/server_hostname_spec.rb | 39 ++ .../preview_server/server_ip_address_spec.rb | 43 ++ middleman-core/spec/spec_helper.rb | 26 + 38 files changed, 2023 insertions(+), 50 deletions(-) create mode 100644 middleman-core/features/cli/preview_server.feature create mode 100755 middleman-core/fixtures/preview-server-app/bin/dns_server.rb create mode 100644 middleman-core/fixtures/preview-server-app/config-complications.rb create mode 100644 middleman-core/fixtures/preview-server-app/config-empty.rb create mode 100644 middleman-core/fixtures/preview-server-app/config.rb create mode 100755 middleman-core/fixtures/preview-server-app/source/index.html.erb create mode 100644 middleman-core/fixtures/preview-server-app/source/layout.erb create mode 100755 middleman-core/fixtures/preview-server-app/source/layouts/custom.erb create mode 100644 middleman-core/fixtures/preview-server-app/source/real.html create mode 100644 middleman-core/fixtures/preview-server-app/source/real/index.html.erb create mode 100644 middleman-core/fixtures/preview-server-app/source/should_be_ignored.html create mode 100644 middleman-core/fixtures/preview-server-app/source/should_be_ignored2.html create mode 100644 middleman-core/fixtures/preview-server-app/source/should_be_ignored3.html create mode 100755 middleman-core/fixtures/preview-server-app/source/static.html create mode 100644 middleman-core/lib/middleman-core/dns_resolver.rb create mode 100644 middleman-core/lib/middleman-core/dns_resolver/basic_network_resolver.rb create mode 100644 middleman-core/lib/middleman-core/dns_resolver/hosts_resolver.rb create mode 100644 middleman-core/lib/middleman-core/dns_resolver/local_link_resolver.rb create mode 100644 middleman-core/lib/middleman-core/dns_resolver/network_resolver.rb create mode 100644 middleman-core/lib/middleman-core/preview_server/checks.rb create mode 100644 middleman-core/lib/middleman-core/preview_server/information.rb create mode 100644 middleman-core/lib/middleman-core/preview_server/network_interface_inventory.rb create mode 100644 middleman-core/lib/middleman-core/preview_server/server_hostname.rb create mode 100644 middleman-core/lib/middleman-core/preview_server/server_information.rb create mode 100644 middleman-core/lib/middleman-core/preview_server/server_information_validator.rb create mode 100644 middleman-core/lib/middleman-core/preview_server/server_ip_address.rb create mode 100644 middleman-core/lib/middleman-core/preview_server/server_url.rb create mode 100644 middleman-core/lib/middleman-core/preview_server/tcp_port_prober.rb create mode 100644 middleman-core/lib/middleman-core/step_definitions/commandline_steps.rb create mode 100644 middleman-core/spec/middleman-core/dns_resolver_spec.rb create mode 100644 middleman-core/spec/middleman-core/preview_server/server_hostname_spec.rb create mode 100644 middleman-core/spec/middleman-core/preview_server/server_ip_address_spec.rb diff --git a/Gemfile b/Gemfile index 6ed44aac..37122c0a 100644 --- a/Gemfile +++ b/Gemfile @@ -20,6 +20,9 @@ gem 'sinatra', '>= 1.4', require: false gem 'redcarpet', '>= 3.1', require: false unless RUBY_ENGINE == 'jruby' gem 'asciidoctor', '~> 0.1', require: false +# Dns server to test preview server +gem 'rubydns', '~> 1.0.1', require: false + # To test javascript gem 'poltergeist', '~> 1.6.0', require: false diff --git a/middleman-core/features/cli/preview_server.feature b/middleman-core/features/cli/preview_server.feature new file mode 100644 index 00000000..f82a0a1f --- /dev/null +++ b/middleman-core/features/cli/preview_server.feature @@ -0,0 +1,532 @@ +Feature: Run the preview server + + As a software developer + I want to start the preview server + In order to view my changes immediately in the browser + + Background: + Given a fixture app "preview-server-app" + And the default aruba timeout is 30 seconds + + Scenario: Start the server with defaults + When I run `middleman server` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + And the output should contain: + """ + View your site at "http:// + """ + And the output should contain: + """ + Inspect your site configuration at "http:// + """ + + Scenario: Start the server with defaults in verbose mode + When I run `middleman server --verbose` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to ":::4567", "0.0.0.0:4567" + """ + And the output should contain: + """ + View your site at "http:// + """ + And the output should contain: + """ + Inspect your site configuration at "http:// + """ + + @ruby-2.1 + Scenario: Start the server with defaults in verbose mode, when a local mdns server resolves the local hostname + Given I start a mdns server for the local hostname + When I run `middleman server --verbose` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to ":::4567", "0.0.0.0:4567" + """ + And the output should contain: + """ + View your site at "http:// + """ + And the output should contain: + """ + Inspect your site configuration at "http:// + """ + + Scenario: Start the server with bind address 127.0.0.1 + Given I have a local hosts file with: + """ + # + 127.0.0.1 localhost.localdomain localhost + """ + When I run `middleman server --verbose --bind-address 127.0.0.1` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to "127.0.0.1:4567" + """ + And the output should contain: + """ + View your site at "http://127.0.0.1:4567" + """ + And the output should contain: + """ + Inspect your site configuration at "http://127.0.0.1:4567/__middleman" + """ + + Scenario: Start the server with bind address 127.0.0.1 configured via config.rb + Given I have a local hosts file with: + """ + # + 127.0.0.1 localhost.localdomain localhost + """ + And a file named "config.rb" with: + """ + set :bind_address, '127.0.0.1' + """ + When I run `middleman server --verbose` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to "127.0.0.1:4567" + """ + And the output should contain: + """ + View your site at "http://127.0.0.1:4567" + """ + And the output should contain: + """ + Inspect your site configuration at "http://127.0.0.1:4567/__middleman" + """ + + Scenario: Start the server with bind address 127.0.0.5 + + This will have no hostname attached because the hosts file, the DNS server + and the MDNS-server do not know anything about 127.0.0.5 + + When I run `middleman server --verbose --bind-address 127.0.0.5` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to "127.0.0.5:4567" + """ + And the output should contain: + """ + View your site at "http://127.0.0.5:4567" + """ + And the output should contain: + """ + Inspect your site configuration at "http://127.0.0.5:4567/__middleman" + """ + + Scenario: Start the server with bind address ::1 + Given a file named ".hosts" with: + """ + # + ::1 localhost.localdomain localhost + """ + When I run `middleman server --verbose --bind-address ::1` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to "::1:4567" + """ + And the output should contain: + """ + View your site at "http://[::1]:4567" + """ + And the output should contain: + """ + Inspect your site configuration at "http://[::1]:4567/__middleman" + """ + + Scenario: Start the server with bind address 0.0.0.0 + When I run `middleman server --verbose --bind-address 0.0.0.0` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to "0.0.0.0:4567" + """ + And the output should contain: + """ + View your site at "http:// + """ + And the output should contain: + """ + Inspect your site configuration at "http:// + """ + + Scenario: Start the server with bind address :: + When I run `middleman server --verbose --bind-address ::` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to ":::4567" + """ + And the output should contain: + """ + View your site at "http:// + """ + And the output should contain: + """ + Inspect your site configuration at "http:// + """ + + Scenario: Start the server with server name "localhost" + Given I have a local hosts file with: + """ + # + 127.0.0.1 localhost.localdomain localhost + """ + When I run `middleman server --verbose --server-name localhost` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to "127.0.0.1:4567" + """ + And the output should contain: + """ + View your site at "http://localhost:4567", "http://127.0.0.1:4567" + """ + And the output should contain: + """ + Inspect your site configuration at "http://localhost:4567/__middleman", "http://127.0.0.1:4567/__middleman" + """ + + Scenario: Start the server with server name "localhost" configured via config.rb + Given I have a local hosts file with: + """ + # + 127.0.0.1 localhost.localdomain localhost + """ + And a file named "config.rb" with: + """ + set :server_name, 'localhost' + """ + When I run `middleman server --verbose` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to "127.0.0.1:4567" + """ + And the output should contain: + """ + View your site at "http://localhost:4567", "http://127.0.0.1:4567" + """ + And the output should contain: + """ + Inspect your site configuration at "http://localhost:4567/__middleman", "http://127.0.0.1:4567/__middleman" + """ + + Scenario: Start the server with server name "localhost" and bind address "127.0.0.1" + Given I have a local hosts file with: + """ + # + 127.0.0.1 localhost.localdomain localhost + """ + When I run `middleman server --verbose --server-name localhost --bind-address 127.0.0.1` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to "127.0.0.1:4567" + """ + And the output should contain: + """ + View your site at "http://localhost:4567", "http://127.0.0.1:4567" + """ + And the output should contain: + """ + Inspect your site configuration at "http://localhost:4567/__middleman", "http://127.0.0.1:4567/__middleman" + """ + + Scenario: Start the server with server name "127.0.0.1" + When I run `middleman server --verbose --server-name 127.0.0.1` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to "127.0.0.1:4567" + """ + And the output should contain: + """ + View your site at "http://127.0.0.1:4567" + """ + And the output should contain: + """ + Inspect your site configuration at "http://127.0.0.1:4567/__middleman" + """ + + Scenario: Start the server with server name "::1" + When I run `middleman server --verbose --server-name ::1` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to "::1:4567" + """ + And the output should contain: + """ + View your site at "http://[::1]:4567" + """ + And the output should contain: + """ + Inspect your site configuration at "http://[::1]:4567/__middleman" + """ + + Scenario: Start the server with https + When I run `middleman server --verbose --https` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to ":::4567", "0.0.0.0:4567" + """ + And the output should contain: + """ + View your site at "https:// + """ + And the output should contain: + """ + Inspect your site configuration at "https:// + """ + + Scenario: Start the server with port 65432 + When I run `middleman server --verbose --port 65432` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to ":::65432", "0.0.0.0:65432" + """ + + Scenario: Start the server with port 65432 configured via config.rb + Given a file named "config.rb" with: + """ + set :port, 65432 + """ + When I run `middleman server --verbose` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to ":::65432", "0.0.0.0:65432" + """ + + Scenario: Start the server when port is blocked by other middleman instance + Given `middleman server` is running in background + When I run `middleman server --verbose` interactively + And I stop all commands if the output of the last command contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman uses a different port + """ + + Scenario: Start the server with bind address 1.1.1.1 + + This should fail, because "1.1.1.1" is not an interface available on this computer. + + Given a file named ".hosts" with: + """ + 1.1.1.1 www.example.com www + """ + When I run `middleman server --verbose --bind-address 1.1.1.1` interactively + And I stop middleman if the output contains: + """ + Running Middleman failed: + """ + Then the output should contain: + """ + Bind address "1.1.1.1" is not available on your system + """ + + Scenario: Start the server with server name www.example.com and bind address 0.0.0.0 + + This should fail, because the user can just use `--server-name`. It does + not make sense for `middleman` to only listen on `0.0.0.0` (IPv4 all + interfaces), but not on `::` (IPv6 all interfaces). There are other tools + like `iptables` (Linux-only) or better some `kernel`-configurations to make + this possible. + + When I run `middleman server --verbose --server-name www.example.com --bind-address 0.0.0.0` interactively + And I stop middleman if the output contains: + """ + Running Middleman failed: + """ + Then the output should contain: + """ + Undefined combination of options "--server-name" and "--bind-address". + """ + + Scenario: Start the server with server name "www.example.com" and bind address "127.0.0.1" + + This should fail because the server name does not resolve to the ip address. + + Given a file named ".hosts" with: + """ + 1.1.1.1 www.example.com www + """ + When I run `middleman server --verbose --server-name www.example.com --bind-address 127.0.0.1` interactively + And I stop middleman if the output contains: + """ + Running Middleman failed: + """ + Then the output should contain: + """ + Server name "www.example.com" does not resolve to bind address "127.0.0.1". Please fix that and try again. + """ + + Scenario: Start the server with server name "garbage.example.com" + When I run `middleman server --verbose --server-name garbage.example.com` interactively + And I stop middleman if the output contains: + """ + Running Middleman failed: + """ + Then the output should contain: + """ + Server name "garbage.example.com" does not resolve to an ip address. Please fix that and try again. + """ + + Scenario: Start the server with server name "www.example.com" and the network name server is used to resolve the server name + Given I have a local hosts file with: + """ + # empty + """ + And I start a mdns server with: + """ + # empty + """ + And I start a dns server with: + """ + www.example.com: 127.0.0.1 + """ + When I run `middleman server --verbose --server-name www.example.com` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to "127.0.0.1:4567" + """ + And the output should contain: + """ + View your site at "http://www.example.com:4567", "http://127.0.0.1:4567" + """ + And the output should contain: + """ + Inspect your site configuration at "http://www.example.com:4567/__middleman", "http://127.0.0.1:4567/__middleman" + """ + + @ruby-2.1 + Scenario: Start the server with server name "host.local" and the link local name server is used to resolve the server name + + To make the mdns resolver resolve a name, it needs to end with ".local". + Otherwise the resolver returns []. + + Given I have a local hosts file with: + """ + # empty + """ + And I start a mdns server with: + """ + host.local: 127.0.0.1 + """ + When I run `middleman server --verbose --server-name host.local` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to "127.0.0.1:4567" + """ + And the output should contain: + """ + View your site at "http://host.local:4567", "http://127.0.0.1:4567" + """ + And the output should contain: + """ + Inspect your site configuration at "http://host.local:4567/__middleman", "http://127.0.0.1:4567/__middleman" + """ + + @ruby-2.1 + Scenario: Start the server with server name "host" and the link local name server is used to resolve the server name + + To make the mdns resolver resolve a name, it needs to end with ".local". If + a plain hostname is given `middleman` appends ".local" automatically. + + Given I have a local hosts file with: + """ + # empty + """ + And I start a mdns server with: + """ + host.local: 127.0.0.1 + """ + When I run `middleman server --verbose --server-name host` interactively + And I stop middleman if the output contains: + """ + Inspect your site configuration + """ + Then the output should contain: + """ + The Middleman preview server is bind to "127.0.0.1:4567" + """ + And the output should contain: + """ + View your site at "http://host.local:4567", "http://127.0.0.1:4567" + """ + And the output should contain: + """ + Inspect your site configuration at "http://host.local:4567/__middleman", "http://127.0.0.1:4567/__middleman" + """ diff --git a/middleman-core/fixtures/preview-server-app/bin/dns_server.rb b/middleman-core/fixtures/preview-server-app/bin/dns_server.rb new file mode 100755 index 00000000..78726f59 --- /dev/null +++ b/middleman-core/fixtures/preview-server-app/bin/dns_server.rb @@ -0,0 +1,33 @@ +#!/usr/bin/env ruby + +require 'rubydns' +require 'psych' + +db_file = ARGV[0] +port = ARGV[1] || 5300 + +db = if File.file? db_file + $stderr.puts 'Found dns db' + Psych.load_file(db_file) + else + $stderr.puts 'Found no dns db. Use default db.' + + { + /www\.example\.org/ => '1.1.1.1' + } + end + +interfaces = [ + [:udp, "127.0.0.1", port], + [:tcp, "127.0.0.1", port] +] + + +# Start the RubyDNS server +RubyDNS::run_server(:listen => interfaces) do + db.each do |matcher, result| + match(matcher, Resolv::DNS::Resource::IN::A) do |transaction| + transaction.respond!(result) + end + end +end diff --git a/middleman-core/fixtures/preview-server-app/config-complications.rb b/middleman-core/fixtures/preview-server-app/config-complications.rb new file mode 100644 index 00000000..14d6c328 --- /dev/null +++ b/middleman-core/fixtures/preview-server-app/config-complications.rb @@ -0,0 +1,11 @@ +page "/fake.html", :proxy => "/real.html", :layout => false + +ignore "/should_be_ignored.html" +page "/should_be_ignored2.html", :ignore => true +page "/target_ignore.html", :proxy => "/should_be_ignored3.html", :ignore => true + +%w(one two).each do |num| + page "/fake/#{num}.html", :proxy => "/real/index.html" do + @num = num + end +end diff --git a/middleman-core/fixtures/preview-server-app/config-empty.rb b/middleman-core/fixtures/preview-server-app/config-empty.rb new file mode 100644 index 00000000..e69de29b diff --git a/middleman-core/fixtures/preview-server-app/config.rb b/middleman-core/fixtures/preview-server-app/config.rb new file mode 100644 index 00000000..14d6c328 --- /dev/null +++ b/middleman-core/fixtures/preview-server-app/config.rb @@ -0,0 +1,11 @@ +page "/fake.html", :proxy => "/real.html", :layout => false + +ignore "/should_be_ignored.html" +page "/should_be_ignored2.html", :ignore => true +page "/target_ignore.html", :proxy => "/should_be_ignored3.html", :ignore => true + +%w(one two).each do |num| + page "/fake/#{num}.html", :proxy => "/real/index.html" do + @num = num + end +end diff --git a/middleman-core/fixtures/preview-server-app/source/index.html.erb b/middleman-core/fixtures/preview-server-app/source/index.html.erb new file mode 100755 index 00000000..f47aba51 --- /dev/null +++ b/middleman-core/fixtures/preview-server-app/source/index.html.erb @@ -0,0 +1 @@ +

Welcome

\ No newline at end of file diff --git a/middleman-core/fixtures/preview-server-app/source/layout.erb b/middleman-core/fixtures/preview-server-app/source/layout.erb new file mode 100644 index 00000000..b72f66e9 --- /dev/null +++ b/middleman-core/fixtures/preview-server-app/source/layout.erb @@ -0,0 +1,9 @@ + + + My Sample Site + + + + <%= yield %> + + \ No newline at end of file diff --git a/middleman-core/fixtures/preview-server-app/source/layouts/custom.erb b/middleman-core/fixtures/preview-server-app/source/layouts/custom.erb new file mode 100755 index 00000000..c8a83373 --- /dev/null +++ b/middleman-core/fixtures/preview-server-app/source/layouts/custom.erb @@ -0,0 +1,8 @@ + + + Custom Layout + + + <%= yield %> + + \ No newline at end of file diff --git a/middleman-core/fixtures/preview-server-app/source/real.html b/middleman-core/fixtures/preview-server-app/source/real.html new file mode 100644 index 00000000..cb312952 --- /dev/null +++ b/middleman-core/fixtures/preview-server-app/source/real.html @@ -0,0 +1 @@ +I am real \ No newline at end of file diff --git a/middleman-core/fixtures/preview-server-app/source/real/index.html.erb b/middleman-core/fixtures/preview-server-app/source/real/index.html.erb new file mode 100644 index 00000000..190d84ec --- /dev/null +++ b/middleman-core/fixtures/preview-server-app/source/real/index.html.erb @@ -0,0 +1,5 @@ +--- +layout: false +--- + +I am real: <%= @num %> \ No newline at end of file diff --git a/middleman-core/fixtures/preview-server-app/source/should_be_ignored.html b/middleman-core/fixtures/preview-server-app/source/should_be_ignored.html new file mode 100644 index 00000000..fb81d5c0 --- /dev/null +++ b/middleman-core/fixtures/preview-server-app/source/should_be_ignored.html @@ -0,0 +1 @@ +

Ignore me!

\ No newline at end of file diff --git a/middleman-core/fixtures/preview-server-app/source/should_be_ignored2.html b/middleman-core/fixtures/preview-server-app/source/should_be_ignored2.html new file mode 100644 index 00000000..0940fd7c --- /dev/null +++ b/middleman-core/fixtures/preview-server-app/source/should_be_ignored2.html @@ -0,0 +1 @@ +

Ignore me! 2

\ No newline at end of file diff --git a/middleman-core/fixtures/preview-server-app/source/should_be_ignored3.html b/middleman-core/fixtures/preview-server-app/source/should_be_ignored3.html new file mode 100644 index 00000000..98007c81 --- /dev/null +++ b/middleman-core/fixtures/preview-server-app/source/should_be_ignored3.html @@ -0,0 +1 @@ +

Ignore me! 3

\ No newline at end of file diff --git a/middleman-core/fixtures/preview-server-app/source/static.html b/middleman-core/fixtures/preview-server-app/source/static.html new file mode 100755 index 00000000..7e50df4e --- /dev/null +++ b/middleman-core/fixtures/preview-server-app/source/static.html @@ -0,0 +1 @@ +Static, no code! \ No newline at end of file diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index f509e943..72c17ee0 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -75,7 +75,11 @@ module Middleman # Which server name should be used # @return [NilClass, String] - config.define_setting :host, nil, 'The preview host name' + config.define_setting :server_name, nil, 'The server name of preview server' + + # Which bind address the preview server should use + # @return [NilClass, String] + config.define_setting :bind_address, nil, 'The bind address of the preview server' # Whether to serve the preview server over HTTPS. # @return [Boolean] diff --git a/middleman-core/lib/middleman-core/cli/server.rb b/middleman-core/lib/middleman-core/cli/server.rb index 47b61b11..8c7d0d06 100644 --- a/middleman-core/lib/middleman-core/cli/server.rb +++ b/middleman-core/lib/middleman-core/cli/server.rb @@ -14,9 +14,12 @@ module Middleman::Cli method_option :port, aliases: '-p', desc: 'The port Middleman will listen on' - method_option :host, - aliases: '-h', - desc: 'The host name Middleman will use' + method_option :server_name, + aliases: '-s', + desc: 'The server name name Middleman will use' + method_option :bind_address, + aliases: '-b', + desc: 'The bind address Middleman will listen on' method_option :https, type: :boolean, desc: 'Serve the preview server over SSL/TLS' @@ -68,8 +71,9 @@ module Middleman::Cli params = { port: options['port'], + bind_address: options['bind_address'], https: options['https'], - host: options['host'], + server_name: options['server_name'], ssl_certificate: options['ssl_certificate'], ssl_private_key: options['ssl_private_key'], environment: options['environment'], diff --git a/middleman-core/lib/middleman-core/dns_resolver.rb b/middleman-core/lib/middleman-core/dns_resolver.rb new file mode 100644 index 00000000..ab49b11f --- /dev/null +++ b/middleman-core/lib/middleman-core/dns_resolver.rb @@ -0,0 +1,73 @@ +require 'resolv' +require 'middleman-core/dns_resolver/network_resolver' +require 'middleman-core/dns_resolver/hosts_resolver' + +module Middleman + # This resolves IP address to names and vice versa + class DnsResolver + private + + attr_reader :resolvers + + public + + # Create resolver + # + # First the local resolver is used. If environment variable HOSTSRC is + # given this file is used for local name lookup. + # + # @param [#getnames, #getaddresses] network_resolver + # The resolver which uses a network name server to resolve ip addresses + # and names. + # + # @param [#getnames, #getaddresses] local_resolver + # The resolver uses /etc/hosts on POSIX-systems and + # C:\Windows\System32\drivers\etc\hosts on Windows-operating systems to + # resolve ip addresses and names. + # + # First the local resolver is queried. If this raises an error or returns + # nil or [] the network resolver is queried. + def initialize(opts={}) + @resolvers = [] + @resolvers << opts.fetch(:hosts_resolver, HostsResolver.new) + + if RUBY_VERSION >= '2.1' + require 'middleman-core/dns_resolver/local_link_resolver' + @resolvers << opts.fetch(:local_link_resolver, LocalLinkResolver.new) + end + + @resolvers << opts.fetch(:network_resolver, NetworkResolver.new) + end + + # Get names for given ip + # + # @param [String] ip + # The ip which should be resolved. + def names_for(ip) + resolvers.each do |r| + names = r.getnames(ip) + + return names unless names.nil? || names.empty? + end + + [] + end + + # Get ips for given name + # + # First the local resolver is used. On POSIX-systems /etc/hosts is used. On + # Windows C:\Windows\System32\drivers\etc\hosts is used. + # + # @param [String] name + # The name which should be resolved. + def ips_for(name) + resolvers.each do |r| + ips = r.getaddresses(name) + + return ips unless ips.nil? || ips.empty? + end + + [] + end + end +end diff --git a/middleman-core/lib/middleman-core/dns_resolver/basic_network_resolver.rb b/middleman-core/lib/middleman-core/dns_resolver/basic_network_resolver.rb new file mode 100644 index 00000000..11dc3096 --- /dev/null +++ b/middleman-core/lib/middleman-core/dns_resolver/basic_network_resolver.rb @@ -0,0 +1,52 @@ +module Middleman + class DnsResolver + # Use network name server to resolve ips and names + class BasicNetworkResolver + private + + attr_reader :resolver, :timeouts + + public + + def initialize(opts={}) + @timeouts = opts.fetch(:timeouts, 2) + end + + # Get names for ip + # + # @param [#to_s] ip + # The ip to resolve into names + # + # @return [Array] + # Array of Names + def getnames(ip) + resolver.getnames(ip.to_s).map(&:to_s) + rescue Resolv::ResolvError, Errno::EADDRNOTAVAIL + [] + end + + # Get ips for name + # + # @param [#to_s] name + # The name to resolve into ips + # + # @return [Array] + # Array of ipaddresses + def getaddresses(name) + resolver.getaddresses(name.to_s).map(&:to_s) + rescue Resolv::ResolvError, Errno::EADDRNOTAVAIL + [] + end + + # Set timeout for lookup + # + # @param [Integer] value + # The timeout value + def timeouts=(timeouts) + return if RUBY_VERSION < '2' + + resolver.timeouts = timeouts + end + end + end +end diff --git a/middleman-core/lib/middleman-core/dns_resolver/hosts_resolver.rb b/middleman-core/lib/middleman-core/dns_resolver/hosts_resolver.rb new file mode 100644 index 00000000..ba3ff997 --- /dev/null +++ b/middleman-core/lib/middleman-core/dns_resolver/hosts_resolver.rb @@ -0,0 +1,63 @@ +module Middleman + class DnsResolver + # Use network name server to resolve ips and names + class HostsResolver + private + + attr_reader :resolver + + public + + def initialize(opts={}) + # using the splat operator works around a non-existing HOSTSRC variable + # using nil as input does not work, but `*[]` does and then Resolv::Hosts + # uses its defaults + @resolver = opts.fetch(:resolver, Resolv::Hosts.new(*hosts_file)) + end + + # Get names for ip + # + # @param [#to_s] ip + # The ip to resolve into names + # + # @return [Array] + # Array of Names + def getnames(ip) + resolver.getnames(ip.to_s).map(&:to_s) + rescue Resolv::ResolvError + [] + end + + # Get ips for name + # + # @param [#to_s] name + # The name to resolve into ips + # + # @return [Array] + # Array of ipaddresses + def getaddresses(name) + resolver.getaddresses(name.to_s).map(&:to_s) + rescue Resolv::ResolvError + [] + end + + private + + # Path to hosts file + # + # This looks for MM_HOSTSRC in your environment + # + # @return [Array] + # This needs to be an array, to make the splat operator work + # + # @example + # # + # 127.0.0.1 localhost.localhost localhost + def hosts_file + return [ENV['MM_HOSTSRC']] if ENV.key?('MM_HOSTSRC') && File.file?(ENV['MM_HOSTSRC']) + + [] + end + end + end +end diff --git a/middleman-core/lib/middleman-core/dns_resolver/local_link_resolver.rb b/middleman-core/lib/middleman-core/dns_resolver/local_link_resolver.rb new file mode 100644 index 00000000..e083d8f3 --- /dev/null +++ b/middleman-core/lib/middleman-core/dns_resolver/local_link_resolver.rb @@ -0,0 +1,44 @@ +require 'middleman-core/dns_resolver/basic_network_resolver' + +module Middleman + class DnsResolver + # Use network name server to resolve ips and names + class LocalLinkResolver < BasicNetworkResolver + def initialize(opts={}) + super + + @timeouts = opts.fetch(:timeouts, 1) + @resolver = opts.fetch(:resolver, Resolv::MDNS.new(nameserver_config)) + + self.timeouts = timeouts + end + + private + + # Hosts + Ports for MDNS resolver + # + # This looks for MM_MDNSRC in your environment. If you are going to use + # IPv6-addresses: Make sure you do not forget to add the port at the end. + # + # MM_MDNSRC=ip:port ip:port + # + # @return [Hash] + # Returns the configuration for the nameserver + # + # @example + # export MM_MDNSRC="224.0.0.251:5353 ff02::fb:5353" + # + def nameserver_config + return unless ENV.key?('MM_MDNSRC') && ENV['MM_MDNSRC'] + + address, port = ENV['MM_MDNSRC'].split(/:/) + + { + nameserver_port: [[address, port.to_i]] + } + rescue StandardError + {} + end + end + end +end diff --git a/middleman-core/lib/middleman-core/dns_resolver/network_resolver.rb b/middleman-core/lib/middleman-core/dns_resolver/network_resolver.rb new file mode 100644 index 00000000..c9db4265 --- /dev/null +++ b/middleman-core/lib/middleman-core/dns_resolver/network_resolver.rb @@ -0,0 +1,42 @@ +require 'middleman-core/dns_resolver/basic_network_resolver' + +module Middleman + class DnsResolver + # Use network name server to resolve ips and names + class NetworkResolver < BasicNetworkResolver + def initialize(opts={}) + super + + @resolver = opts.fetch(:resolver, Resolv::DNS.new(nameserver_config)) + self.timeouts = timeouts + end + + private + + # Hosts + Ports for MDNS resolver + # + # This looks for MM_MDNSRC in your environment. If you are going to use + # IPv6-addresses: Make sure you do not forget to add the port at the end. + # + # MM_MDNSRC=ip:port ip:port + # + # @return [Hash] + # Returns the configuration for the nameserver + # + # @example + # export MM_MDNSRC="224.0.0.251:5353 ff02::fb:5353" + # + def nameserver_config + return unless ENV.key?('MM_DNSRC') && ENV['MM_DNSRC'] + + address, port = ENV['MM_DNSRC'].split(/:/) + + { + nameserver_port: [[address, port.to_i]] + } + rescue StandardError + {} + end + end + end +end diff --git a/middleman-core/lib/middleman-core/preview_server.rb b/middleman-core/lib/middleman-core/preview_server.rb index 1e81b4e6..9076b2fa 100644 --- a/middleman-core/lib/middleman-core/preview_server.rb +++ b/middleman-core/lib/middleman-core/preview_server.rb @@ -1,15 +1,16 @@ require 'webrick' require 'webrick/https' require 'openssl' -require 'socket' require 'middleman-core/meta_pages' require 'middleman-core/logger' +require 'middleman-core/preview_server/server_information' +require 'middleman-core/preview_server/server_url' # rubocop:disable GlobalVars module Middleman - module PreviewServer + class PreviewServer class << self - attr_reader :app, :host, :port, :ssl_certificate, :ssl_private_key, :environment + attr_reader :app, :ssl_certificate, :ssl_private_key, :environment, :server_information delegate :logger, to: :app def https? @@ -19,13 +20,31 @@ module Middleman # Start an instance of Middleman::Application # @return [void] def start(opts={}) + # Do not buffer output, otherwise testing of output does not work + $stdout.sync = true + $stderr.sync = true + @options = opts + @server_information = ServerInformation.new - mount_instance(new_app) + # New app evaluates the middleman configuration. Since this can be + # invalid as well, we need to evaluate the configuration BEFORE + # checking for validity + the_app = new_app + # And now comes the check + unless server_information.valid? + logger.fatal %(== Running Middleman failed: #{server_information.reason}. Please fix that and try again.) + exit 1 + end + + mount_instance(the_app) + + logger.debug %(== Server information is provided by #{server_information.handler}) logger.debug %(== The Middleman is running in "#{environment}" environment) - logger.info "== The Middleman is standing watch at #{uri} (#{uri(public_ip)})" - logger.info "== Inspect your site configuration at #{uri + '__middleman'}" + logger.debug format('== The Middleman preview server is bind to %s', ServerUrl.new(hosts: server_information.listeners, port: server_information.port, https: https?).to_bind_addresses.join(', ')) + logger.info format('== View your site at %s', ServerUrl.new(hosts: server_information.site_addresses, port: server_information.port, https: https?).to_urls.join(', ')) + logger.info format('== Inspect your site configuration at %s', ServerUrl.new(hosts: server_information.site_addresses, port: server_information.port, https: https?).to_config_urls.join(', ')) @initialized ||= false return if @initialized @@ -116,18 +135,26 @@ module Middleman opts[:instrumenting] || false ) - config[:environment] = opts[:environment].to_sym if opts[:environment] - config[:port] = opts[:port] if opts[:port] - config[:host] = opts[:host].presence || Socket.gethostname.tr(' ', '+') - config[:https] = opts[:https] unless opts[:https].nil? + config[:environment] = opts[:environment].to_sym if opts[:environment] + config[:port] = opts[:port] if opts[:port] + config[:bind_address] = opts[:bind_address] + config[:server_name] = opts[:server_name] + config[:https] = opts[:https] unless opts[:https].nil? config[:ssl_certificate] = opts[:ssl_certificate] if opts[:ssl_certificate] config[:ssl_private_key] = opts[:ssl_private_key] if opts[:ssl_private_key] end - @host = @app.config[:host] - @port = @app.config[:port] - @https = @app.config[:https] - @environment = @app.config[:environment] + # store configured port to make a check later on possible + configured_port = @app.config[:port] + + # Use configuration values to set `bind_address` etc. in + # `server_information` + server_information.use @app.config + + logger.warn format('== The Middleman uses a different port "%s" then the configured one "%s" because some other server is listening on that port.', server_information.port, configured_port) unless @app.config[:port] == configured_port + + @https = @app.config[:https] + @environment = @app.config[:environment] @ssl_certificate = @app.config[:ssl_certificate] @ssl_private_key = @app.config[:ssl_private_key] @@ -190,9 +217,10 @@ module Middleman # @return [void] def setup_webrick(is_logging) http_opts = { - Port: port, + Port: server_information.port, AccessLog: [], - ServerName: host, + ServerName: server_information.server_name, + BindAddress: server_information.bind_address.to_s, DoNotReverseLookup: true } @@ -205,7 +233,7 @@ module Middleman http_opts[:SSLPrivateKey] = OpenSSL::PKey::RSA.new File.read ssl_private_key else # use a generated self-signed cert - cert, key = create_self_signed_cert(1024, [['CN', host]], 'Middleman Preview Server') + cert, key = create_self_signed_cert(1024, [['CN', server_information.server_name]], server_information.site_addresses, 'Middleman Preview Server') http_opts[:SSLCertificate] = cert http_opts[:SSLPrivateKey] = key end @@ -217,20 +245,17 @@ module Middleman http_opts[:Logger] = ::WEBrick::Log.new(nil, 0) end - attempts_left = 4 - tried_ports = [] begin ::WEBrick::HTTPServer.new(http_opts) rescue Errno::EADDRINUSE - logger.error "== Port #{port} is unavailable. Either close the instance of Middleman already running on #{port} or start this Middleman on a new port with: --port=#{unused_tcp_port}" - exit(1) + logger.error %(== Port "#{http_opts[:Port]}" is in use. This should not have happened. Please start "middleman server" again.) end end # Copy of https://github.com/nahi/ruby/blob/webrick_trunk/lib/webrick/ssl.rb#L39 # that uses a different serial number each time the cert is generated in order to # avoid errors in Firefox. Also doesn't print out stuff to $stderr unnecessarily. - def create_self_signed_cert(bits, cn, comment) + def create_self_signed_cert(bits, cn, aliases, comment) rsa = OpenSSL::PKey::RSA.new(bits) cert = OpenSSL::X509::Certificate.new cert.version = 2 @@ -254,6 +279,8 @@ module Middleman aki = ef.create_extension('authorityKeyIdentifier', 'keyid:always,issuer:always') cert.add_extension(aki) + cert.add_extension ef.create_extension('subjectAltName', aliases.map { |d| "DNS: #{d}" }.join(',')) + cert.sign(rsa, OpenSSL::Digest::SHA1.new) [cert, rsa] @@ -306,29 +333,6 @@ module Middleman end end end - - # Returns the URI the preview server will run on - # @return [URI] - def uri(host=@host) - scheme = https? ? 'https' : 'http' - URI("#{scheme}://#{host}:#{@port}/") - end - - # An IPv4 address on this machine which should be externally addressable. - # @return [String] - def public_ip - ip = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? } - ip ? ip.ip_address : '127.0.0.1' - end - - # Returns unused TCP port - # @return [Fixnum] - def unused_tcp_port - server = TCPServer.open(0) - port = server.addr[1] - server.close - port - end end class FilteredWebrickLog < ::WEBrick::Log diff --git a/middleman-core/lib/middleman-core/preview_server/checks.rb b/middleman-core/lib/middleman-core/preview_server/checks.rb new file mode 100644 index 00000000..e4302acf --- /dev/null +++ b/middleman-core/lib/middleman-core/preview_server/checks.rb @@ -0,0 +1,81 @@ +require 'ipaddr' + +module Middleman + class PreviewServer + # Checks for input of preview server + module Checks + # This one will get all default setup + class BasicCheck; end + + # This checks if the server name resolves to the bind_address + # + # If the users enters: + # + # 1. server_name: www.example.com (10.0.0.1) + # 2. bind_address: 127.0.0.01 + # + # This validation will fail + class ServerNameResolvesToBindAddress < BasicCheck + private + + attr_reader :resolver + + public + + def initialize + @resolver = DnsResolver.new + end + + # Validate + # + # @param [Information] information + # The information to be validated + def validate(information) + return if resolver.ips_for(information.server_name).include? information.bind_address + + information.valid = false + information.reason = format('Server name "%s" does not resolve to bind address "%s"', information.server_name, information.bind_address) + end + end + + # This validation fails if the user chooses to use an ip address which is + # not available on his/her system + class InterfaceIsAvailableOnSystem < BasicCheck + # Validate + # + # @param [Information] information + # The information to be validated + def validate(information) + return if information.bind_address.blank? || information.local_network_interfaces.include?(information.bind_address.to_s) || %w(0.0.0.0 ::).any? { |b| information.bind_address == b } || IPAddr.new('127.0.0.0/8').include?(information.bind_address.to_s) + + information.valid = false + information.reason = format('Bind address "%s" is not available on your system. Please use one of %s', information.bind_address, information.local_network_interfaces.map { |i| %("#{i}") }.join(', ')) + end + end + + # This one requires a bind address if the user entered a server name + # + # If the `bind_address` is blank this check will fail + class RequiresBindAddressIfServerNameIsGiven < BasicCheck + def validate(information) + return unless information.bind_address.blank? + + information.valid = false + information.reason = format('Server name "%s" does not resolve to an ip address', information.server_name) + end + end + + # This validation always fails + class DenyAnyAny < BasicCheck + # Validate + # + # @param [Information] information + # The information to be validated + def validate(information) + information.valid = false + information.reason = 'Undefined combination of options "--server-name" and "--bind-address". If you think this is wrong, please file a bug at "https://github.com/middleman/middleman"' + end + end + end + end +end diff --git a/middleman-core/lib/middleman-core/preview_server/information.rb b/middleman-core/lib/middleman-core/preview_server/information.rb new file mode 100644 index 00000000..4518cfb2 --- /dev/null +++ b/middleman-core/lib/middleman-core/preview_server/information.rb @@ -0,0 +1,273 @@ +require 'ipaddr' +require 'active_support/core_ext/object/blank' +require 'middleman-core/preview_server/checks' +require 'middleman-core/preview_server/server_hostname' +require 'middleman-core/preview_server/server_ip_address' + +module Middleman + class PreviewServer + # Basic information class to wrap common behaviour + class BasicInformation + private + + attr_reader :checks, :network_interfaces_inventory + + public + + attr_accessor :bind_address, :server_name, :port, :reason, :valid + attr_reader :listeners, :site_addresses + + # Create instance + # + # @param [String] bind_address + # The bind address of the server + # + # @param [String] server_name + # The name of the server + # + # @param [Integer] port + # The port to listen on + def initialize(opts={}) + @bind_address = ServerIpAddress.new(opts[:bind_address]) + @server_name = ServerHostname.new(opts[:server_name]) + @port = opts[:port] + @valid = true + + @site_addresses = [] + @listeners = [] + @checks = [] + + # This needs to be check for each use case. Otherwise `Webrick` will + # complain about that. + @checks << Checks::InterfaceIsAvailableOnSystem.new + end + + # Is the given information valid? + def valid? + valid == true + end + + # Pass "self" to validator + # + # @param [#validate] validator + # The validator + def validate_me(validator) + validator.validate self, checks + end + + def resolve_me(*) + fail NoMethodError + end + + # Get network information + # + # @param [#network_interfaces] inventory + # Get list of available network interfaces + def show_me_network_interfaces(inventory) + @network_interfaces_inventory = inventory + end + + # Default is to get all network interfaces + def local_network_interfaces + network_interfaces_inventory.nil? ? [] : network_interfaces_inventory.network_interfaces(:all) + end + end + + # This only is used if no other parser is available + # + # The "default" behaviour is to fail because of "Checks::DenyAnyAny" + class DefaultInformation < BasicInformation + def initialize(*args) + super + + # Make this fail + @checks << Checks::DenyAnyAny.new + end + + def resolve_me(*); end + + # Always true + def self.matches?(*) + true + end + end + + # This one is used if no bind address and no server name is given + class AllInterfaces < BasicInformation + def initialize(*args) + super + + after_init + end + + def self.matches?(opts={}) + opts[:bind_address].blank? && opts[:server_name].blank? + end + + # Resolve ips + def resolve_me(resolver) + hostname = ServerHostname.new(Socket.gethostname) + hostname_ips = resolver.ips_for(hostname) + network_interface = ServerIpAddress.new(Array(local_network_interfaces).first) + resolved_name = ServerHostname.new(resolver.names_for(network_interface).first) + + if includes_array? local_network_interfaces, hostname_ips + @server_name = hostname + @site_addresses << hostname + + network_interface = ServerIpAddress.new((local_network_interfaces & hostname_ips).first) + elsif RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ + @server_name = hostname + @site_addresses << hostname + elsif !resolved_name.blank? + @server_name = resolved_name + @site_addresses << resolved_name + else + @server_name = network_interface + end + + @site_addresses << network_interface + + self + end + + private + + def includes_array?(a, b) + !(a & b).empty? + end + + def after_init + @listeners << ServerIpAddress.new('::') + @listeners << ServerIpAddress.new('0.0.0.0') + end + end + + # This is used if bind address is 0.0.0.0, the server name needs to be + # blank + class AllIpv4Interfaces < AllInterfaces + def self.matches?(opts={}) + opts[:bind_address] == '0.0.0.0' && opts[:server_name].blank? + end + + # Use only ipv4 interfaces + def local_network_interfaces + network_interfaces_inventory.nil? ? [] : network_interfaces_inventory.network_interfaces(:ipv4) + end + + private + + def after_init + @listeners << ServerIpAddress.new('0.0.0.0') + end + end + + # This is used if bind address is ::, the server name needs to be blank + class AllIpv6Interfaces < AllInterfaces + def self.matches?(opts={}) + opts[:bind_address] == '::' && opts[:server_name].blank? + end + + # Use only ipv6 interfaces + def local_network_interfaces + network_interfaces_inventory.nil? ? [] : network_interfaces_inventory.network_interfaces(:ipv6) + end + + private + + def after_init + @listeners << ServerIpAddress.new('::') + end + end + + # Used if a bind address is given and the server name is blank + class BindAddressInformation < BasicInformation + def initialize(*args) + super + + @listeners << bind_address + @site_addresses << bind_address + end + + def self.matches?(opts={}) + !opts[:bind_address].blank? && opts[:server_name].blank? + end + + # Resolv + def resolve_me(resolver) + @server_name = ServerHostname.new(resolver.names_for(bind_address).first) + @site_addresses << @server_name unless @server_name.blank? + + self + end + end + + # Use if server name is given and bind address is blank + class ServerNameInformation < BasicInformation + def initialize(*args) + super + + @checks << Checks::RequiresBindAddressIfServerNameIsGiven.new + @site_addresses << server_name + end + + def resolve_me(resolver) + @bind_address = ServerIpAddress.new(resolver.ips_for(server_name).first) + + unless bind_address.blank? + @listeners << bind_address + @site_addresses << bind_address + end + + self + end + + def self.matches?(opts={}) + opts[:bind_address].blank? && !opts[:server_name].blank? + end + end + + # Only used if bind address and server name are given and bind address is + # not :: or 0.0.0.0 + class BindAddressAndServerNameInformation < BasicInformation + def initialize(*args) + super + + @listeners << bind_address + @site_addresses << server_name + @site_addresses << bind_address + + @checks << Checks::ServerNameResolvesToBindAddress.new + end + + def self.matches?(opts={}) + !opts[:bind_address].blank? && !opts[:server_name].blank? && !%w(:: 0.0.0.0).include?(opts[:bind_address]) + end + + def resolve_me(*); end + end + + # If the server name is either an ipv4 or ipv6 address, e.g. 127.0.0.1 or + # ::1, use this one + class ServerNameIsIpInformation < BasicInformation + def initialize(opts={}) + super + + ip = ServerIpAddress.new(server_name.to_s) + + @listeners << ip + @site_addresses << ip + end + + def resolve_me(*); end + + def self.matches?(opts={}) + ip = IPAddr.new(opts[:server_name]) + + ip.ipv4? || ip.ipv6? + rescue + false + end + end + end +end diff --git a/middleman-core/lib/middleman-core/preview_server/network_interface_inventory.rb b/middleman-core/lib/middleman-core/preview_server/network_interface_inventory.rb new file mode 100644 index 00000000..d9ba1229 --- /dev/null +++ b/middleman-core/lib/middleman-core/preview_server/network_interface_inventory.rb @@ -0,0 +1,65 @@ +require 'middleman-core/preview_server/server_ip_address' + +module Middleman + class PreviewServer + # This holds information about local network interfaces on the user systemd + class NetworkInterfaceInventory + # Return all ip interfaces + class All + def network_interfaces + ipv4_addresses = Socket.ip_address_list.select(&:ipv4?).map { |ai| ServerIpv4Address.new(ai.ip_address) } + ipv6_addresses = Socket.ip_address_list.select(&:ipv6?).map { |ai| ServerIpv6Address.new(ai.ip_address) } + + ipv4_addresses + ipv6_addresses + end + + def self.match?(*) + true + end + end + + # Return all ipv4 interfaces + class Ipv4 + def network_interfaces + Socket.ip_address_list.select { |ai| ai.ipv4? && !ai.ipv4_loopback? }.map { |ai| ServerIpv4Address.new(ai.ip_address) } + end + + def self.match?(type) + :ipv4 == type + end + end + + # Return all ipv6 interfaces + class Ipv6 + def network_interfaces + Socket.ip_address_list.select { |ai| ai.ipv6? && !ai.ipv6_loopback? }.map { |ai| ServerIpv6Address.new(ai.ip_address) } + end + + def self.match?(type) + :ipv6 == type + end + end + + private + + attr_reader :types + + public + + def initialize + @types = [] + @types << Ipv4 + @types << Ipv6 + @types << All + end + + # Return ip interfaces + # + # @param [Symbol] type + # The type of interface which should be returned + def network_interfaces(type=:all) + types.find { |t| t.match? type.to_sym }.new.network_interfaces + end + end + end +end diff --git a/middleman-core/lib/middleman-core/preview_server/server_hostname.rb b/middleman-core/lib/middleman-core/preview_server/server_hostname.rb new file mode 100644 index 00000000..9df133cb --- /dev/null +++ b/middleman-core/lib/middleman-core/preview_server/server_hostname.rb @@ -0,0 +1,39 @@ +module Middleman + class PreviewServer + class ServerHostname + class ServerFullHostname < SimpleDelegator + def to_s + __getobj__ + end + + def self.match?(*) + true + end + + alias_method :to_browser, :to_s + end + + class ServerPlainHostname < SimpleDelegator + def to_s + __getobj__ + '.local' + end + + def self.match?(name) + # rubocop:disable Style/CaseEquality + name != 'localhost' && /^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?\.?$/ === name + # rubocop:enable Style/CaseEquality + end + + alias_method :to_browser, :to_s + end + + def self.new(string) + @names = [] + @names << ServerPlainHostname + @names << ServerFullHostname + + @names.find { |n| n.match? string }.new(string) + end + end + end +end diff --git a/middleman-core/lib/middleman-core/preview_server/server_information.rb b/middleman-core/lib/middleman-core/preview_server/server_information.rb new file mode 100644 index 00000000..937efdd5 --- /dev/null +++ b/middleman-core/lib/middleman-core/preview_server/server_information.rb @@ -0,0 +1,144 @@ +require 'middleman-core/dns_resolver' +require 'middleman-core/preview_server/information' +require 'middleman-core/preview_server/network_interface_inventory' +require 'middleman-core/preview_server/tcp_port_prober' +require 'middleman-core/preview_server/server_information_validator' + +module Middleman + class PreviewServer + # This class holds all information which the preview server needs to setup a listener + # + # * server name + # * bind address + # * port + # + # Furthermore it probes for a free tcp port, if the default one 4567 is not available. + class ServerInformation + private + + attr_reader :resolver, :validator, :network_interface_inventory, :informations, :tcp_port_prober + + public + + def initialize(opts={}) + @resolver = opts.fetch(:resolver, DnsResolver.new) + @validator = opts.fetch(:validator, ServerInformationValidator.new) + @network_interface_inventory = opts.fetch(:network_interface_inventory, NetworkInterfaceInventory.new) + @tcp_port_prober = opts.fetch(:tcp_port_prober, TcpPortProber.new) + + @informations = [] + @informations << AllInterfaces + @informations << AllIpv4Interfaces + @informations << AllIpv6Interfaces + @informations << ServerNameIsIpInformation + @informations << ServerNameInformation + @informations << BindAddressInformation + @informations << BindAddressAndServerNameInformation + @informations << DefaultInformation + end + + # The information + # + # Is cached + def information + return @information if @information + + # The `DefaultInformation`-class always returns `true`, so there's + # always a klass available and find will never return nil + listener_klass = informations.find { |l| l.matches? bind_address: @bind_address, server_name: @server_name } + @information = listener_klass.new(bind_address: @bind_address, server_name: @server_name) + + @information.show_me_network_interfaces(network_interface_inventory) + @information.resolve_me(resolver) + @information.port = tcp_port_prober.port(@port) + @information.validate_me(validator) + + @information + end + + # Use a middleman configuration to get information + # + # @param [#[]] config + # The middleman config + def use(config) + @bind_address = config[:bind_address] + @port = config[:port] + @server_name = config[:server_name] + + config[:bind_address] = bind_address + config[:port] = port + config[:server_name] = server_name + end + + # Make information of internal server class avaible to make debugging + # easier. This can be used to log the class which was used to determine + # the preview server settings + # + # @return [String] + # The name of the class + def handler + information.class.to_s + end + + # Is the server information valid? + # + # This is used to output a helpful error message, which can be stored in + # `#reason`. + # + # @return [TrueClass, FalseClass] + # The result + def valid? + information.valid? + end + + # The reason why the information is NOT valid + # + # @return [String] + # The reason why the information is not valid + def reason + information.reason + end + + # The server name + # + # @return [String] + # The name of the server + def server_name + information.server_name + end + + # The bind address of server + # + # @return [String] + # The bind address of the server + def bind_address + information.bind_address + end + + # The port on which the server should listen + # + # @return [Integer] + # The port number + def port + information.port + end + + # A list of site addresses + # + # @return [Array] + # A list of addresses which can be used to access the middleman preview + # server + def site_addresses + information.site_addresses + end + + # A list of listeners + # + # @return [Array] + # A list of bind address where the + def listeners + information.listeners + end + end + end +end diff --git a/middleman-core/lib/middleman-core/preview_server/server_information_validator.rb b/middleman-core/lib/middleman-core/preview_server/server_information_validator.rb new file mode 100644 index 00000000..ff2eeb2e --- /dev/null +++ b/middleman-core/lib/middleman-core/preview_server/server_information_validator.rb @@ -0,0 +1,18 @@ +module Middleman + class PreviewServer + # Validate user input + class ServerInformationValidator + # Validate the input + # + # @param [ServerInformation] information + # The information instance which holds information about the preview + # server settings + # + # @param [Array] checks + # A list of checks which should be evaluated + def validate(information, checks) + checks.each { |c| c.validate information } + end + end + end +end diff --git a/middleman-core/lib/middleman-core/preview_server/server_ip_address.rb b/middleman-core/lib/middleman-core/preview_server/server_ip_address.rb new file mode 100644 index 00000000..55a83db5 --- /dev/null +++ b/middleman-core/lib/middleman-core/preview_server/server_ip_address.rb @@ -0,0 +1,55 @@ +require 'ipaddr' +require 'forwardable' + +module Middleman + class PreviewServer + class ServerIpAddress + def self.new(ip_address) + @parser = [] + @parser << ServerIpv6Address + @parser << ServerIpv4Address + + @parser.find { |p| p.match? ip_address }.new(ip_address) + end + end + + class BasicServerIpAddress < SimpleDelegator + end + + class ServerIpv4Address < BasicServerIpAddress + def to_browser + __getobj__.to_s + end + + def self.match?(*) + true + end + end + + class ServerIpv6Address < BasicServerIpAddress + def to_s + __getobj__.sub(/%.*$/, '') + end + + def to_browser + format('[%s]', to_s) + end + + if RUBY_VERSION < '2' + def self.match?(str) + str = str.to_s.sub(/%.*$/, '') + IPAddr.new(str).ipv6? + rescue StandardError + false + end + else + def self.match?(str) + str = str.to_s.sub(/%.*$/, '') + IPAddr.new(str).ipv6? + rescue IPAddr::InvalidAddressError, IPAddr::AddressFamilyError + false + end + end + end + end +end diff --git a/middleman-core/lib/middleman-core/preview_server/server_url.rb b/middleman-core/lib/middleman-core/preview_server/server_url.rb new file mode 100644 index 00000000..9b7a5b29 --- /dev/null +++ b/middleman-core/lib/middleman-core/preview_server/server_url.rb @@ -0,0 +1,50 @@ +require 'ipaddr' + +module Middleman + class PreviewServer + # This builds the server urls for the preview server + class ServerUrl + private + + attr_reader :hosts, :port, :https + + public + + def initialize(opts={}) + @hosts = opts.fetch(:hosts) + @port = opts.fetch(:port) + @https = opts.fetch(:https, false) + end + + # Return bind addresses + # + # @return [Array] + # List of bind addresses of format host:port + def to_bind_addresses + hosts.map { |l| format('"%s:%s"', l.to_s, port) } + end + + # Return server urls + # + # @return [Array] + # List of urls of format http://host:port + def to_urls + hosts.map { |l| format('"%s://%s:%s"', https? ? 'https' : 'http', l.to_browser, port) } + end + + # Return server config urls + # + # @return [Array] + # List of urls of format http://host:port/__middleman + def to_config_urls + hosts.map { |l| format('"%s://%s:%s/__middleman"', https? ? 'https' : 'http', l.to_browser, port) } + end + + private + + def https? + https == true + end + end + end +end diff --git a/middleman-core/lib/middleman-core/preview_server/tcp_port_prober.rb b/middleman-core/lib/middleman-core/preview_server/tcp_port_prober.rb new file mode 100644 index 00000000..c480f91b --- /dev/null +++ b/middleman-core/lib/middleman-core/preview_server/tcp_port_prober.rb @@ -0,0 +1,29 @@ +module Middleman + class PreviewServer + # Probe for tcp ports + # + # This one first tries `try_port` if this is not available use the free + # port returned by TCPServer. + class TcpPortProber + # Check for port + # + # @param [Integer] try_port + # The port to be checked + # + # @return [Integer] + # The port + def port(try_port) + server = TCPServer.open(try_port) + server.close + + try_port + rescue + server = TCPServer.open(0) + port = server.addr[1] + server.close + + port + end + end + end +end diff --git a/middleman-core/lib/middleman-core/step_definitions.rb b/middleman-core/lib/middleman-core/step_definitions.rb index 95245f14..25c4790a 100644 --- a/middleman-core/lib/middleman-core/step_definitions.rb +++ b/middleman-core/lib/middleman-core/step_definitions.rb @@ -3,6 +3,7 @@ require 'aruba/jruby' require 'middleman-core/step_definitions/middleman_steps' require 'middleman-core/step_definitions/builder_steps' require 'middleman-core/step_definitions/server_steps' +require 'middleman-core/step_definitions/commandline_steps' # Monkeypatch for windows support module ArubaMonkeypatch diff --git a/middleman-core/lib/middleman-core/step_definitions/commandline_steps.rb b/middleman-core/lib/middleman-core/step_definitions/commandline_steps.rb new file mode 100644 index 00000000..5a663c32 --- /dev/null +++ b/middleman-core/lib/middleman-core/step_definitions/commandline_steps.rb @@ -0,0 +1,88 @@ +When /^I stop (?:middleman|all commands) if the output( of the last command)? contains:$/ do |last_command, expected| + begin + Timeout.timeout(exit_timeout) do + loop do + fail "You need to start middleman interactively first." unless @interactive + + if unescape(@interactive.output) =~ Regexp.new(unescape(expected)) + only_processes.each { |p| p.terminate } + break + end + + sleep 0.1 + end + end + rescue ChildProcess::TimeoutError, TimeoutError + @interactive.terminate + ensure + announcer.stdout @interactive.stdout + announcer.stderr @interactive.stderr + end +end + +# Make it just a long running process +Given /`(.*?)` is running in background/ do |cmd| + run(cmd, 120) +end + +Given /I have a local hosts file with:/ do |string| + step 'I set the environment variables to:', table( + %( + | variable | value | + | MM_HOSTSRC | .hosts | + ) + ) + + step 'a file named ".hosts" with:', string +end + +Given /I start a dns server with:/ do |string| + @dns_server.terminate if defined? @dns_server + + port = 5300 + db_file = 'dns.db' + + step 'I set the environment variables to:', table( + %( + | variable | value | + | MM_DNSRC | 127.0.0.1:#{port}| + ) + ) + + set_env 'PATH', File.expand_path(File.join(current_dir, 'bin')) + ':' + ENV['PATH'] + write_file db_file, string + + @dns_server = run("dns_server.rb #{db_file} #{port}", 120) +end + +Given /I start a mdns server with:/ do |string| + @mdns_server.terminate if defined? @mdns_server + + port = 5301 + db_file = 'mdns.db' + + step 'I set the environment variables to:', table( + %( + | variable | value | + | MM_MDNSRC | 127.0.0.1:#{port}| + ) + ) + + set_env 'PATH', File.expand_path(File.join(current_dir, 'bin')) + ':' + ENV['PATH'] + write_file db_file, string + + @mdns_server = run("dns_server.rb #{db_file} #{port}", 120) +end + +Given /I start a mdns server for the local hostname/ do + step %(I start a mdns server with:), "#{Socket.gethostname}: 127.0.0.1" +end + +# Make sure each and every process is really dead +After do + only_processes.each { |p| p.terminate } +end + +Before '@ruby-2.1' do + skip_this_scenario if RUBY_VERSION < '2.1' +end diff --git a/middleman-core/spec/middleman-core/dns_resolver_spec.rb b/middleman-core/spec/middleman-core/dns_resolver_spec.rb new file mode 100644 index 00000000..8e5b2251 --- /dev/null +++ b/middleman-core/spec/middleman-core/dns_resolver_spec.rb @@ -0,0 +1,118 @@ +require 'spec_helper' +require 'middleman-core/dns_resolver' + +RSpec.describe Middleman::DnsResolver do + subject(:resolver) do + described_class.new( + hosts_resolver: hosts_resolver, + local_link_resolver: local_link_resolver, + network_resolver: network_resolver + ) + end + + let(:hosts_resolver) { instance_double('Middleman::DnsResolver::HostsResolver') } + let(:local_link_resolver) { instance_double('Middleman::DnsResolver::LocalLinkResolver') } + let(:network_resolver) { instance_double('Middleman::DnsResolver::NetworkResolver') } + + before :each do + allow(network_resolver).to receive(:timeouts=) + end + + describe '#names_for' do + context 'when hosts resolver can resolve name' do + before :each do + expect(hosts_resolver).to receive(:getnames).with(unresolved_ip).and_return(resolved_names) + if RUBY_VERSION >= '2.1' + expect(local_link_resolver).not_to receive(:getnames) + end + expect(network_resolver).not_to receive(:getnames) + end + + let(:unresolved_ip) { '127.0.0.1' } + let(:resolved_names) { %w(localhost) } + + it { expect(resolver.names_for(unresolved_ip)).to eq resolved_names } + end + + context 'when local link resolver can resolve name' do + before :each do + expect(hosts_resolver).to receive(:getnames).with(unresolved_ip).and_return([]) + if RUBY_VERSION >= '2.1' + expect(local_link_resolver).to receive(:getnames).with(unresolved_ip).and_return(resolved_names) + expect(network_resolver).not_to receive(:getnames) + else + expect(network_resolver).to receive(:getnames).with(unresolved_ip).and_return(resolved_names) + end + end + + let(:unresolved_ip) { '127.0.0.1' } + let(:resolved_names) { %w(localhost) } + + it { expect(resolver.names_for(unresolved_ip)).to eq resolved_names } + end + + context 'when network resolver can resolve name' do + before :each do + expect(hosts_resolver).to receive(:getnames).with(unresolved_ip).and_return([]) + if RUBY_VERSION >= '2.1' + expect(local_link_resolver).to receive(:getnames).with(unresolved_ip).and_return([]) + end + expect(network_resolver).to receive(:getnames).with(unresolved_ip).and_return(resolved_names) + end + + let(:unresolved_ip) { '127.0.0.1' } + let(:resolved_names) { %w(localhost) } + + it { expect(resolver.names_for(unresolved_ip)).to eq resolved_names } + end + end + + describe '#ips_for' do + context 'when hosts resolver can resolve name' do + before :each do + expect(hosts_resolver).to receive(:getaddresses).with(unresolved_ips).and_return(resolved_name) + if RUBY_VERSION >= '2.1' + expect(local_link_resolver).not_to receive(:getaddresses) + end + expect(network_resolver).not_to receive(:getaddresses) + end + + let(:unresolved_ips) { '127.0.0.1' } + let(:resolved_name) { %w(localhost) } + + it { expect(resolver.ips_for(unresolved_ips)).to eq resolved_name } + end + + context 'when local link resolver can resolve name' do + before :each do + expect(hosts_resolver).to receive(:getaddresses).with(unresolved_ips).and_return([]) + if RUBY_VERSION >= '2.1' + expect(local_link_resolver).to receive(:getaddresses).with(unresolved_ips).and_return(resolved_name) + expect(network_resolver).not_to receive(:getaddresses) + else + expect(network_resolver).to receive(:getaddresses).with(unresolved_ips).and_return(resolved_name) + end + end + + let(:unresolved_ips) { '127.0.0.1' } + let(:resolved_name) { %w(localhost) } + + it { expect(resolver.ips_for(unresolved_ips)).to eq resolved_name } + end + + context 'when network resolver can resolve name' do + before :each do + expect(hosts_resolver).to receive(:getaddresses).with(unresolved_ips).and_return([]) + if RUBY_VERSION >= '2.1' + expect(local_link_resolver).to receive(:getaddresses).with(unresolved_ips).and_return([]) + end + expect(network_resolver).to receive(:getaddresses).with(unresolved_ips).and_return(resolved_name) + end + + let(:unresolved_ips) { '127.0.0.1' } + let(:resolved_name) { %w(localhost) } + + it { expect(resolver.ips_for(unresolved_ips)).to eq resolved_name } + end + end +end diff --git a/middleman-core/spec/middleman-core/preview_server/server_hostname_spec.rb b/middleman-core/spec/middleman-core/preview_server/server_hostname_spec.rb new file mode 100644 index 00000000..b0dc6a07 --- /dev/null +++ b/middleman-core/spec/middleman-core/preview_server/server_hostname_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' +require 'middleman-core/preview_server/server_hostname' + +RSpec.describe Middleman::PreviewServer::ServerHostname do + subject(:hostname) { described_class.new(string) } + let(:string) { 'www.example.com' } + + describe '#to_s' do + context 'when hostname' do + it { expect(hostname.to_s).to eq string } + end + + context 'when ipv4' do + let(:string) { '127.0.0.1' } + it { expect(hostname.to_s).to eq string } + end + + context 'when ipv6' do + let(:string) { '2607:f700:8000:12e:b3d9:1cba:b52:aa1b' } + it { expect(hostname.to_s).to eq string } + end + end + + describe '#to_browser' do + context 'when hostname' do + it { expect(hostname.to_browser).to eq string } + end + + context 'when ipv4' do + let(:string) { '127.0.0.1' } + it { expect(hostname.to_browser).to eq string } + end + + context 'when ipv6' do + let(:string) { '::1' } + it { expect(hostname.to_browser).to eq string } + end + end +end diff --git a/middleman-core/spec/middleman-core/preview_server/server_ip_address_spec.rb b/middleman-core/spec/middleman-core/preview_server/server_ip_address_spec.rb new file mode 100644 index 00000000..a82fec63 --- /dev/null +++ b/middleman-core/spec/middleman-core/preview_server/server_ip_address_spec.rb @@ -0,0 +1,43 @@ +require 'spec_helper' +require 'middleman-core/preview_server/server_ip_address' + +RSpec.describe Middleman::PreviewServer::ServerIpAddress do + subject(:ip_address) { described_class.new(string) } + let(:string) { '127.0.0.1' } + + describe '#to_s' do + context 'when ipv4' do + let(:string) { '127.0.0.1' } + it { expect(ip_address.to_s).to eq string } + end + + context 'when ipv6' do + context 'without suffix' do + let(:string) { '2607:f700:8000:12e:b3d9:1cba:b52:aa1b' } + it { expect(ip_address.to_s).to eq string } + end + + context 'with suffix' do + let(:string) { '2607:f700:8000:12e:b3d9:1cba:b52:aa1b%wlp1s0' } + let(:result) { '2607:f700:8000:12e:b3d9:1cba:b52:aa1b' } + it { expect(ip_address.to_s).to eq result } + end + end + end + + describe '#to_browser' do + context 'when ip_address' do + it { expect(ip_address.to_browser).to eq string } + end + + context 'when ipv4' do + let(:string) { '127.0.0.1' } + it { expect(ip_address.to_browser).to eq string } + end + + context 'when ipv6' do + let(:string) { '2607:f700:8000:12e:b3d9:1cba:b52:aa1b' } + it { expect(ip_address.to_browser).to eq "[#{string}]" } + end + end +end diff --git a/middleman-core/spec/spec_helper.rb b/middleman-core/spec/spec_helper.rb index a9d71768..32c25a34 100644 --- a/middleman-core/spec/spec_helper.rb +++ b/middleman-core/spec/spec_helper.rb @@ -3,3 +3,29 @@ SimpleCov.root(File.expand_path(File.dirname(__FILE__) + '/..')) require 'coveralls' Coveralls.wear! + +require 'aruba/api' +RSpec.configure do |config| + config.include Aruba::Api +end + +# encoding: utf-8 +RSpec.configure do |config| + config.filter_run :focus + config.run_all_when_everything_filtered = true + + config.default_formatter = 'doc' if config.files_to_run.one? + + # config.profile_examples = 10 + config.order = :random + Kernel.srand config.seed + + config.expect_with :rspec do |expectations| + expectations.syntax = :expect + end + + config.mock_with :rspec do |mocks| + mocks.syntax = :expect + mocks.verify_partial_doubles = true + end +end From c14fd72d04231755528b64066987033f3ffb9832 Mon Sep 17 00:00:00 2001 From: Mauro Otonelli Date: Tue, 14 Jul 2015 19:26:59 -0300 Subject: [PATCH 067/364] Remove unused integer/inflections extension. --- middleman-core/lib/middleman-core/application.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index f509e943..5fcf8ffc 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -8,10 +8,6 @@ require 'i18n' # users expect. ::I18n.enforce_available_locales = false -# Use ActiveSupport JSON -require 'active_support/json' -require 'active_support/core_ext/integer/inflections' - # Simple callback library require 'hooks' From 63d6a00ed9dbcf7150fd0c4dbe296bf1cbc4bc5e Mon Sep 17 00:00:00 2001 From: Mauro Otonelli Date: Tue, 14 Jul 2015 19:30:17 -0300 Subject: [PATCH 068/364] Use native Ruby JSON implementation instead of ActiveSupport's. --- middleman-core/lib/middleman-core/core_extensions/data.rb | 4 ++-- .../lib/middleman-core/core_extensions/front_matter.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/middleman-core/lib/middleman-core/core_extensions/data.rb b/middleman-core/lib/middleman-core/core_extensions/data.rb index 4f8a0e50..0f25c223 100644 --- a/middleman-core/lib/middleman-core/core_extensions/data.rb +++ b/middleman-core/lib/middleman-core/core_extensions/data.rb @@ -9,7 +9,7 @@ module Middleman def registered(app) # Data formats require 'yaml' - require 'active_support/json' + require 'json' app.config.define_setting :data_dir, 'data', 'The directory data files are stored in' app.send :include, InstanceMethods @@ -98,7 +98,7 @@ module Middleman if %w(.yaml .yml).include?(extension) data = YAML.load_file(full_path) elsif extension == '.json' - data = ActiveSupport::JSON.decode(full_path.read) + data = JSON.parse(full_path.read) else return end diff --git a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb index 8499a339..982a6d70 100644 --- a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb @@ -5,7 +5,7 @@ require 'pathname' require 'yaml' # Parsing JSON frontmatter -require 'active_support/json' +require 'json' # Extensions namespace module Middleman::CoreExtensions @@ -154,7 +154,7 @@ module Middleman::CoreExtensions begin json = ($1 + $2).sub(';;;', '{').sub(';;;', '}') - data = ActiveSupport::JSON.decode(json).symbolize_keys + data = JSON.parse(json).symbolize_keys rescue => e app.logger.error "JSON Exception parsing #{full_path}: #{e.message}" return false From d18e5ed973eb5d4a3de6bb1bc5a27fb3855d2bfd Mon Sep 17 00:00:00 2001 From: Mauro Otonelli Date: Tue, 14 Jul 2015 21:32:52 -0300 Subject: [PATCH 069/364] Locked aruba to ~> 0.7.4, as 0.8 (latest) breaks the build. --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index f34fbaec..2740f00c 100644 --- a/Gemfile +++ b/Gemfile @@ -6,7 +6,7 @@ gem 'yard', '~> 0.8', require: false # Test tools gem 'pry', '~> 0.10', group: :development -gem 'aruba', '~> 0.6' +gem 'aruba', '~> 0.7.4' gem 'rspec', '~> 3.0' gem 'fivemat', '~> 1.3' gem 'cucumber', '~> 1.3' From 55f909d9cfa7f04b77d90dadea09496c2ab936fb Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 15 Jul 2015 14:08:51 -0700 Subject: [PATCH 070/364] Attempt to help #1563 --- middleman-core/lib/middleman-more/extensions/asset_hash.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-more/extensions/asset_hash.rb b/middleman-core/lib/middleman-more/extensions/asset_hash.rb index e44218ee..7a7e5148 100644 --- a/middleman-core/lib/middleman-more/extensions/asset_hash.rb +++ b/middleman-core/lib/middleman-more/extensions/asset_hash.rb @@ -91,7 +91,7 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension dirpath = Pathname.new(File.dirname(path)) # TODO: This regex will change some paths in plan HTML (not in a tag) - is that OK? - body.gsub(/([=\'\"\(,]\s*)([^\s\'\"\)]+(#{@exts_regex_text}))/) do |match| + body.gsub(/([=\'\"\(,]\s*)([^\s\'\"\)]{1,255}#{@exts_regex_text})/) do |match| opening_character = $1 asset_path = $2 From 68a6eacc333b283bf90df1519a4b55660fa82de3 Mon Sep 17 00:00:00 2001 From: Mauro Otonelli Date: Wed, 15 Jul 2015 22:03:41 -0300 Subject: [PATCH 071/364] Removed most deprecation warnings from the build. --- .../step_definitions/builder_steps.rb | 14 +++++----- .../step_definitions/server_steps.rb | 27 +++++++++---------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/middleman-core/lib/middleman-core/step_definitions/builder_steps.rb b/middleman-core/lib/middleman-core/step_definitions/builder_steps.rb index 21266e26..e57bb51b 100644 --- a/middleman-core/lib/middleman-core/step_definitions/builder_steps.rb +++ b/middleman-core/lib/middleman-core/step_definitions/builder_steps.rb @@ -6,8 +6,8 @@ end Given /^app "([^\"]*)" is using config "([^\"]*)"$/ do |path, config_name| target = File.join(PROJECT_ROOT_PATH, 'fixtures', path) - config_path = File.join(current_dir, "config-#{config_name}.rb") - config_dest = File.join(current_dir, 'config.rb') + config_path = File.join(current_directory, "config-#{config_name}.rb") + config_dest = File.join(current_directory, 'config.rb') FileUtils.cp(config_path, config_dest) end @@ -22,12 +22,12 @@ Given /^a fixture app "([^\"]*)"$/ do |path| # This step can be reentered from several places but we don't want # to keep re-copying and re-cd-ing into ever-deeper directories - next if File.basename(current_dir) == path + next if File.basename(current_directory) == path step %Q{a directory named "#{path}"} target_path = File.join(PROJECT_ROOT_PATH, 'fixtures', path) - FileUtils.cp_r(target_path, current_dir) + FileUtils.cp_r(target_path, current_directory) step %Q{I cd to "#{path}"} end @@ -58,12 +58,12 @@ Given /^a successfully built app at "([^\"]*)" with flags "([^\"]*)"$/ do |path, end Given /^a modification time for a file named "([^\"]*)"$/ do |file| - target = File.join(current_dir, file) + target = File.join(current_directory, file) @modification_times[target] = File.mtime(target) end Then /^the file "([^\"]*)" should not have been updated$/ do |file| - target = File.join(current_dir, file) + target = File.join(current_directory, file) File.mtime(target).should == @modification_times[target] end @@ -73,5 +73,5 @@ Then /^the file "([^"]*)" should contain '([^']*)'$/ do |file, partial_content| end And /the file "(.*)" should be gzipped/ do |file| - expect(File.binread(File.join(current_dir, file), 2)).to eq(['1F8B'].pack('H*')) + expect(File.binread(File.join(current_directory, file), 2)).to eq(['1F8B'].pack('H*')) end diff --git a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb index 5f2f2886..52a13d6e 100644 --- a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb +++ b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb @@ -31,8 +31,7 @@ Given /^current environment is "([^\"]*)"$/ do |env| end Given /^the Server is running$/ do - root_dir = File.expand_path(current_dir) - + root_dir = File.expand_path(current_directory) if File.exists?(File.join(root_dir, 'source')) ENV['MM_SOURCE'] = 'source' @@ -48,7 +47,7 @@ Given /^the Server is running$/ do set :show_exceptions, false } - in_current_dir do + in_current_directory do @server_inst = Middleman::Application.server.inst do initialize_commands.each do |p| instance_exec(&p) @@ -69,62 +68,62 @@ Given /^a template named "([^\"]*)" with:$/ do |name, string| end When /^I go to "([^\"]*)"$/ do |url| - in_current_dir do + in_current_directory do visit(URI.encode(url).to_s) end end Then /^going to "([^\"]*)" should not raise an exception$/ do |url| - in_current_dir do - + in_current_directory do + expect{ visit(URI.encode(url).to_s) }.to_not raise_exception end end Then /^the content type should be "([^\"]*)"$/ do |expected| - in_current_dir do + in_current_directory do expect(page.response_headers['Content-Type']).to start_with expected end end Then /^I should see "([^\"]*)"$/ do |expected| - in_current_dir do + in_current_directory do expect(page.body).to include expected end end Then /^I should see '([^\']*)'$/ do |expected| - in_current_dir do + in_current_directory do expect(page.body).to include expected end end Then /^I should see:$/ do |expected| - in_current_dir do + in_current_directory do expect(page.body).to include expected end end Then /^I should not see "([^\"]*)"$/ do |expected| - in_current_dir do + in_current_directory do expect(page.body).not_to include expected end end Then /^I should not see:$/ do |expected| - in_current_dir do + in_current_directory do expect(page.body).not_to include expected end end Then /^the status code should be "([^\"]*)"$/ do |expected| - in_current_dir do + in_current_directory do expect(page.status_code).to eq expected.to_i end end Then /^I should see "([^\"]*)" lines$/ do |lines| - in_current_dir do + in_current_directory do expect(page.body.chomp.split($/).length).to eq lines.to_i end end From df13c62a6bf5e82e13b267f4fd419501243a3088 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Thu, 16 Jul 2015 11:34:46 -0700 Subject: [PATCH 072/364] Revert "Attempt to help #1563" This reverts commit 55f909d9cfa7f04b77d90dadea09496c2ab936fb. --- middleman-core/lib/middleman-more/extensions/asset_hash.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-more/extensions/asset_hash.rb b/middleman-core/lib/middleman-more/extensions/asset_hash.rb index 7a7e5148..e44218ee 100644 --- a/middleman-core/lib/middleman-more/extensions/asset_hash.rb +++ b/middleman-core/lib/middleman-more/extensions/asset_hash.rb @@ -91,7 +91,7 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension dirpath = Pathname.new(File.dirname(path)) # TODO: This regex will change some paths in plan HTML (not in a tag) - is that OK? - body.gsub(/([=\'\"\(,]\s*)([^\s\'\"\)]{1,255}#{@exts_regex_text})/) do |match| + body.gsub(/([=\'\"\(,]\s*)([^\s\'\"\)]+(#{@exts_regex_text}))/) do |match| opening_character = $1 asset_path = $2 From c11a9e6f39948ff653fe9a1c59a9e555bcbb65cf Mon Sep 17 00:00:00 2001 From: Mauro Otonelli Date: Sun, 19 Jul 2015 20:45:10 -0300 Subject: [PATCH 073/364] Removed invalid Rubocop blocks. --- .rubocop.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 68908de8..836f048b 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -23,14 +23,10 @@ ClassLength: Enabled: false Documentation: Enabled: false -Encoding: - Enabled: false HashSyntax: EnforcedStyle: ruby19 SpaceAroundEqualsInParameterDefault: EnforcedStyle: no_space -Blocks: - Enabled: false PerlBackrefs: Enabled: false ClassAndModuleChildren: From dcc52d967cfd9577d7899ea0141a2b886c29a693 Mon Sep 17 00:00:00 2001 From: Mauro Otonelli Date: Sun, 19 Jul 2015 20:45:45 -0300 Subject: [PATCH 074/364] Applied Rubocop feedback. --- middleman-core/lib/middleman-core/cli/extension.rb | 4 ++-- middleman-core/lib/middleman-core/configuration.rb | 2 -- .../lib/middleman-core/core_extensions/rendering.rb | 3 +-- middleman-core/lib/middleman-core/extension.rb | 1 - .../lib/middleman-core/sitemap/extensions/proxies.rb | 1 - .../lib/middleman-more/core_extensions/default_helpers.rb | 6 +++--- middleman-core/lib/middleman-more/core_extensions/i18n.rb | 4 ++-- middleman-core/lib/middleman-more/extensions/lorem.rb | 4 ++-- .../lib/middleman-more/extensions/relative_assets.rb | 2 +- 9 files changed, 11 insertions(+), 16 deletions(-) diff --git a/middleman-core/lib/middleman-core/cli/extension.rb b/middleman-core/lib/middleman-core/cli/extension.rb index 1065514f..c6ababd9 100644 --- a/middleman-core/lib/middleman-core/cli/extension.rb +++ b/middleman-core/lib/middleman-core/cli/extension.rb @@ -35,13 +35,13 @@ module Middleman::Cli # Output a .gitignore file class_option :git, type: :boolean, default: true - no_tasks { + no_tasks do # Write a .gitignore file for project # @return [void] def generate_gitignore! return unless options[:git] copy_file 'gitignore', File.join(name, '.gitignore') end - } + end end end diff --git a/middleman-core/lib/middleman-core/configuration.rb b/middleman-core/lib/middleman-core/configuration.rb index 6c227504..e1cff713 100644 --- a/middleman-core/lib/middleman-core/configuration.rb +++ b/middleman-core/lib/middleman-core/configuration.rb @@ -118,7 +118,6 @@ module Middleman # Set the value of a setting by key. Creates the setting if it doesn't exist. # @param [Symbol] key # @param [Object] val - # rubocop:disable UselessSetterCall def []=(key, val) setting_obj = setting(key) || define_setting(key) setting_obj.value = val @@ -228,7 +227,6 @@ module Middleman end # Whether or not there has been a value set beyond the default - # rubocop:disable TrivialAccessors def value_set? @value_set end diff --git a/middleman-core/lib/middleman-core/core_extensions/rendering.rb b/middleman-core/lib/middleman-core/core_extensions/rendering.rb index d1c361ee..11e1cbb0 100644 --- a/middleman-core/lib/middleman-core/core_extensions/rendering.rb +++ b/middleman-core/lib/middleman-core/core_extensions/rendering.rb @@ -428,7 +428,7 @@ module Middleman layout_path = locate_layout(layout_name, current_engine) - if !layout_path + unless layout_path raise ::Middleman::CoreExtensions::Rendering::TemplateNotFound, "Could not locate layout: #{layout_name}" end @@ -462,7 +462,6 @@ module Middleman end # The currently rendering engine - # rubocop:disable TrivialAccessors # @return [Symbol, nil] def current_engine=(v) @_current_engine = v diff --git a/middleman-core/lib/middleman-core/extension.rb b/middleman-core/lib/middleman-core/extension.rb index 3a21000c..311375b7 100644 --- a/middleman-core/lib/middleman-core/extension.rb +++ b/middleman-core/lib/middleman-core/extension.rb @@ -130,7 +130,6 @@ module Middleman @klass.after_configuration do ext.after_configuration if ext.respond_to?(:after_configuration) - # rubocop:disable IfUnlessModifier if ext.respond_to?(:manipulate_resource_list) ext.app.sitemap.register_resource_list_manipulator(ext.class.extension_name, ext) end diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb index 8fb29cc8..54ca3d5e 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb @@ -17,7 +17,6 @@ module Middleman module ResourceInstanceMethods # Whether this page is a proxy - # rubocop:disable TrivialAccessors # @return [Boolean] def proxy? @proxied_to diff --git a/middleman-core/lib/middleman-more/core_extensions/default_helpers.rb b/middleman-core/lib/middleman-more/core_extensions/default_helpers.rb index cbb94768..3fe8d680 100644 --- a/middleman-core/lib/middleman-more/core_extensions/default_helpers.rb +++ b/middleman-core/lib/middleman-more/core_extensions/default_helpers.rb @@ -102,13 +102,13 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension # Override helper to add `relative` opt-out. def stylesheet_link_tag(*sources) options = { - :rel => 'stylesheet' + rel: 'stylesheet' }.update(sources.extract_options!.symbolize_keys) path_options = {} path_options[:relative] = options.delete(:relative) if options.key?(:relative) - sources.flatten.inject(ActiveSupport::SafeBuffer.new) do |all,source| + sources.flatten.inject(ActiveSupport::SafeBuffer.new) do |all, source| all << tag(:link, { href: asset_path(:css, source, path_options) }.update(options)) @@ -122,7 +122,7 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension path_options = {} path_options[:relative] = options.delete(:relative) if options.key?(:relative) - sources.flatten.inject(::ActiveSupport::SafeBuffer.new) do |all,source| + sources.flatten.inject(::ActiveSupport::SafeBuffer.new) do |all, source| all << content_tag(:script, nil, { src: asset_path(:js, source, path_options) }.update(options)) diff --git a/middleman-core/lib/middleman-more/core_extensions/i18n.rb b/middleman-core/lib/middleman-more/core_extensions/i18n.rb index 318b2b47..2c041a83 100644 --- a/middleman-core/lib/middleman-more/core_extensions/i18n.rb +++ b/middleman-core/lib/middleman-more/core_extensions/i18n.rb @@ -245,10 +245,10 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension ::I18n.locale = lang localized_page_id = ::I18n.t("paths.#{page_id}", default: page_id, fallback: []) - partially_localized_path = "" + partially_localized_path = '' File.dirname(path).split('/').each do |path_sub| - next if path_sub == "" + next if path_sub == '' partially_localized_path = "#{partially_localized_path}/#{(::I18n.t("paths.#{path_sub}", default: path_sub).to_s)}" end diff --git a/middleman-core/lib/middleman-more/extensions/lorem.rb b/middleman-core/lib/middleman-more/extensions/lorem.rb index 32f1c6c1..91a0612d 100644 --- a/middleman-core/lib/middleman-more/extensions/lorem.rb +++ b/middleman-core/lib/middleman-more/extensions/lorem.rb @@ -152,8 +152,8 @@ class Middleman::Extensions::Lorem < ::Middleman::Extension color = options[:color] if options[:random_color] - background_color = hex.shuffle[0...6].join - color = hex.shuffle[0...6].join + background_color = hex.sample(6).join + color = hex.sample(6).join end src << "/#{background_color.sub(/^#/, '')}" if background_color diff --git a/middleman-core/lib/middleman-more/extensions/relative_assets.rb b/middleman-core/lib/middleman-more/extensions/relative_assets.rb index 95eb291b..28024a2e 100644 --- a/middleman-core/lib/middleman-more/extensions/relative_assets.rb +++ b/middleman-core/lib/middleman-more/extensions/relative_assets.rb @@ -18,7 +18,7 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension def asset_url(path, prefix='', options={}) options[:relative] = true unless options.key?(:relative) - path = super(path, prefix, options) + super(path, prefix, options) end end end From 0a8ceb24b0b0007c007fb83798c9c2ab175ac460 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 20 Jul 2015 12:13:10 -0700 Subject: [PATCH 075/364] Add test for #1568 --- middleman-core/features/chained_templates.feature | 5 ++++- .../chained-app/source/test.html.combobreaker.str.erb | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 middleman-core/fixtures/chained-app/source/test.html.combobreaker.str.erb diff --git a/middleman-core/features/chained_templates.feature b/middleman-core/features/chained_templates.feature index 7f538b65..4647e7eb 100644 --- a/middleman-core/features/chained_templates.feature +++ b/middleman-core/features/chained_templates.feature @@ -13,10 +13,13 @@ Feature: Templates should be chainable When I cd to "build" Then the following files should exist: | index.html | - + | test.html.combobreaker | And the file "index.html" should contain "Title" And the file "index.html" should contain "Subtitle" And the file "index.html" should contain "Sup" + And the file "test.html.combobreaker.html" should contain "Title" + And the file "test.html.combobreaker.html" should contain "Subtitle" + And the file "test.html.combobreaker.html" should contain "Sup" Scenario: Partials are parsed by multiple template engines: Outer template has .erb and inner .md.erb Given a fixture app "partial-chained_templates-app" diff --git a/middleman-core/fixtures/chained-app/source/test.html.combobreaker.str.erb b/middleman-core/fixtures/chained-app/source/test.html.combobreaker.str.erb new file mode 100644 index 00000000..3b7caec2 --- /dev/null +++ b/middleman-core/fixtures/chained-app/source/test.html.combobreaker.str.erb @@ -0,0 +1,8 @@ +--- +layout: false +sup: "Sup" +--- + +

#{"<%= data.article.title %>"}

+

#{"<%= data.article.subtitle %>"}

+

#{"<%= current_page.data.sup %>"}

From c69099c451e7cf7d66265b4c11ab056b6169fe31 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 22 Jul 2015 14:32:14 -0700 Subject: [PATCH 076/364] Really fix #1568 --- .travis.yml | 2 ++ Gemfile | 2 +- middleman-core/features/chained_templates.feature | 8 ++++---- ...combobreaker.str.erb => test.erb.combobreaker.str.erb} | 0 middleman-core/lib/middleman-core/sitemap/store.rb | 2 +- .../lib/middleman-core/step_definitions/server_steps.rb | 1 - 6 files changed, 8 insertions(+), 7 deletions(-) rename middleman-core/fixtures/chained-app/source/{test.html.combobreaker.str.erb => test.erb.combobreaker.str.erb} (100%) diff --git a/.travis.yml b/.travis.yml index 492342aa..71acb01f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,8 @@ rvm: os: - linux - osx +cache: bundler +sudo: false matrix: fast_finish: true allow_failures: diff --git a/Gemfile b/Gemfile index 21951896..7c355f39 100644 --- a/Gemfile +++ b/Gemfile @@ -9,7 +9,7 @@ gem 'pry', '~> 0.10', group: :development gem 'aruba', '~> 0.7.4' gem 'rspec', '~> 3.0' gem 'fivemat', '~> 1.3' -gem 'cucumber', '~> 2.0' +gem 'cucumber', '~> 1.3' # Optional middleman dependencies, included for tests gem 'less', '2.3', require: false diff --git a/middleman-core/features/chained_templates.feature b/middleman-core/features/chained_templates.feature index 4647e7eb..aed75b7c 100644 --- a/middleman-core/features/chained_templates.feature +++ b/middleman-core/features/chained_templates.feature @@ -13,13 +13,13 @@ Feature: Templates should be chainable When I cd to "build" Then the following files should exist: | index.html | - | test.html.combobreaker | + | test.erb.combobreaker | And the file "index.html" should contain "Title" And the file "index.html" should contain "Subtitle" And the file "index.html" should contain "Sup" - And the file "test.html.combobreaker.html" should contain "Title" - And the file "test.html.combobreaker.html" should contain "Subtitle" - And the file "test.html.combobreaker.html" should contain "Sup" + And the file "test.erb.combobreaker" should contain "Title" + And the file "test.erb.combobreaker" should contain "Subtitle" + And the file "test.erb.combobreaker" should contain "Sup" Scenario: Partials are parsed by multiple template engines: Outer template has .erb and inner .md.erb Given a fixture app "partial-chained_templates-app" diff --git a/middleman-core/fixtures/chained-app/source/test.html.combobreaker.str.erb b/middleman-core/fixtures/chained-app/source/test.erb.combobreaker.str.erb similarity index 100% rename from middleman-core/fixtures/chained-app/source/test.html.combobreaker.str.erb rename to middleman-core/fixtures/chained-app/source/test.erb.combobreaker.str.erb diff --git a/middleman-core/lib/middleman-core/sitemap/store.rb b/middleman-core/lib/middleman-core/sitemap/store.rb index 589a8ab6..a5541349 100644 --- a/middleman-core/lib/middleman-core/sitemap/store.rb +++ b/middleman-core/lib/middleman-core/sitemap/store.rb @@ -242,7 +242,7 @@ module Middleman # @return [String] def remove_templating_extensions(path) # Strip templating extensions as long as Tilt knows them - path = path.sub(File.extname(path), '') while ::Tilt[path] + path = path.sub(/#{::Regexp.escape(File.extname(path))}$/, '') while ::Tilt[path] path end diff --git a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb index 52a13d6e..0d2d7a92 100644 --- a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb +++ b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb @@ -75,7 +75,6 @@ end Then /^going to "([^\"]*)" should not raise an exception$/ do |url| in_current_directory do - expect{ visit(URI.encode(url).to_s) }.to_not raise_exception end end From 63e9cd9b5f70915b122dfee531e9b1b8262177c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20G=C3=BCnnewig?= Date: Tue, 21 Jul 2015 10:28:11 +0200 Subject: [PATCH 077/364] Substitue whitespace in name --- .../lib/middleman-core/preview_server/server_hostname.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/middleman-core/lib/middleman-core/preview_server/server_hostname.rb b/middleman-core/lib/middleman-core/preview_server/server_hostname.rb index 9df133cb..833daa4d 100644 --- a/middleman-core/lib/middleman-core/preview_server/server_hostname.rb +++ b/middleman-core/lib/middleman-core/preview_server/server_hostname.rb @@ -3,7 +3,7 @@ module Middleman class ServerHostname class ServerFullHostname < SimpleDelegator def to_s - __getobj__ + __getobj__.gsub(/\s/, '+') end def self.match?(*) @@ -15,7 +15,7 @@ module Middleman class ServerPlainHostname < SimpleDelegator def to_s - __getobj__ + '.local' + __getobj__.gsub(/\s/, '+') + '.local' end def self.match?(name) From 7bfacd565ae65574c397cb663a9db81a5cf1f25d Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 22 Jul 2015 11:24:57 -0700 Subject: [PATCH 078/364] Update change log --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9378726..0a461146 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ master * Add retina files support on automatic_image_sizes * Fix woff/woff2 confusion in asset hashing. * Support `relative: false` on `stylesheet_link_tag` and `javascript_include_tag` +* New host detection in preview server. Provides better externally accessible host/ip information for connecting from mobile devices and virtual machines. 3.3.12 === From a52865903423a85de6715eec8c204b6558f4e7ee Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Fri, 24 Jul 2015 14:20:04 -0700 Subject: [PATCH 079/364] Bump listen to 3.0 --- middleman-core/middleman-core.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/middleman-core.gemspec b/middleman-core/middleman-core.gemspec index 91fa76d3..844e6de9 100644 --- a/middleman-core/middleman-core.gemspec +++ b/middleman-core/middleman-core.gemspec @@ -36,7 +36,7 @@ Gem::Specification.new do |s| s.add_dependency("padrino-helpers", ["~> 0.12.3"]) # Watcher - s.add_dependency("listen", [">= 2.7.9", "< 3.0"]) + s.add_dependency("listen", ["~> 3.0.3"]) # i18n s.add_dependency("i18n", ["~> 0.7.0"]) From 837a679aa737d08131eaf6bc3db506d570bf809d Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Fri, 24 Jul 2015 14:51:20 -0700 Subject: [PATCH 080/364] bump thor --- Gemfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index 7c355f39..785849f1 100644 --- a/Gemfile +++ b/Gemfile @@ -32,8 +32,8 @@ gem 'therubyrhino', '>= 2.0', platforms: :jruby # Code Quality gem 'rubocop', '~> 0.24', require: false -gem 'simplecov', '0.9', require: false -gem 'coveralls', '~> 0.7', require: false +gem 'simplecov', '~> 0.10', require: false +gem 'coveralls', '~> 0.8', require: false # Middleman itself gem 'middleman', path: 'middleman' From 0fba2ae2f6d645e8ce9d99d677007672db174cd6 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 5 Aug 2015 13:37:03 -0700 Subject: [PATCH 081/364] Fix config meta page --- .../lib/middleman-core/extension_manager.rb | 3 ++- .../lib/middleman-core/extensions.rb | 2 +- .../lib/middleman-core/meta_pages.rb | 7 +++++- .../meta_pages/templates/config.html.erb | 24 +++++++++---------- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/middleman-core/lib/middleman-core/extension_manager.rb b/middleman-core/lib/middleman-core/extension_manager.rb index 916713b0..4e2040eb 100644 --- a/middleman-core/lib/middleman-core/extension_manager.rb +++ b/middleman-core/lib/middleman-core/extension_manager.rb @@ -3,13 +3,14 @@ module Middleman extend Forwardable def_delegator :@app, :logger - def_delegators :@activated, :[] + def_delegators :@activated, :[], :each def initialize(app) @app = app @activated = {} manager = self + { before_sitemap: :before_sitemap, initialized: :before_configuration diff --git a/middleman-core/lib/middleman-core/extensions.rb b/middleman-core/lib/middleman-core/extensions.rb index fa51796d..42fbdb2d 100644 --- a/middleman-core/lib/middleman-core/extensions.rb +++ b/middleman-core/lib/middleman-core/extensions.rb @@ -106,7 +106,7 @@ module Middleman # A flattened list of all extensions which are automatically activated # @return [Array] A list of extension names which are automatically activated. def auto_activated - @auto_activate.values.flat_map(&:name) + @auto_activate.values.map(&:to_a).flatten.map(&:name) end # @api private diff --git a/middleman-core/lib/middleman-core/meta_pages.rb b/middleman-core/lib/middleman-core/meta_pages.rb index cd789ef1..f5478ae5 100644 --- a/middleman-core/lib/middleman-core/meta_pages.rb +++ b/middleman-core/lib/middleman-core/meta_pages.rb @@ -61,9 +61,13 @@ module Middleman def config(_) global_config = @middleman.config.all_settings.map { |c| ConfigSetting.new(c) } extension_config = {} + auto_activated_config = {} @middleman.extensions.each do |ext_name, extension| - next if ::Middleman::Extension.auto_activated.include? ext_name + if ::Middleman::Extensions.auto_activated.include? ext_name + auto_activated_config[ext_name] = extension_options(extension) + next + end if extension.is_a?(Hash) # Multiple instance extension @@ -82,6 +86,7 @@ module Middleman template('config.html.erb', global_config: global_config, extension_config: extension_config, + auto_activated_config: auto_activated_config, registered_extensions: Middleman::Extensions.registered.dup) end diff --git a/middleman-core/lib/middleman-core/meta_pages/templates/config.html.erb b/middleman-core/lib/middleman-core/meta_pages/templates/config.html.erb index 44e55388..d2b29847 100644 --- a/middleman-core/lib/middleman-core/meta_pages/templates/config.html.erb +++ b/middleman-core/lib/middleman-core/meta_pages/templates/config.html.erb @@ -29,22 +29,22 @@

Extensions

    - <% extension_config.each do |ext_name, configs| %> -
  • - <% registered_extensions.delete(ext_name) %> + <% [extension_config, auto_activated_config].each do |extensions| %> + <% extensions.each do |ext_name, configs| %> +
  • + <% registered_extensions.delete(ext_name) %> - :<%= ext_name %> + :<%= ext_name %> - - <% if configs && !configs.empty? %> -
      - <% configs.each do |setting| %> -
    • <%= setting.render %>
    • + <% if configs && !configs.empty? %> +
        + <% configs.each do |setting| %> +
      • <%= setting.render %>
      • + <% end %> +
      <% end %> -
    +
  • <% end %> - - <% end %> <% registered_extensions.keys.each do |ext_name| %> From dc4057d8dc56b7507f393978756080ec5c4ce062 Mon Sep 17 00:00:00 2001 From: Max Meyer Date: Wed, 5 Aug 2015 22:51:25 +0200 Subject: [PATCH 082/364] Bump version of cucumber --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 785849f1..28cc9224 100644 --- a/Gemfile +++ b/Gemfile @@ -9,7 +9,7 @@ gem 'pry', '~> 0.10', group: :development gem 'aruba', '~> 0.7.4' gem 'rspec', '~> 3.0' gem 'fivemat', '~> 1.3' -gem 'cucumber', '~> 1.3' +gem 'cucumber', '~> 2.0' # Optional middleman dependencies, included for tests gem 'less', '2.3', require: false From dcbeb7dc76bd29584ed8ef3bed8d74afc9488ecc Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Thu, 6 Aug 2015 11:06:34 -0700 Subject: [PATCH 083/364] Remove fivemat --- Gemfile | 1 - gem_rake_helper.rb | 4 ++-- middleman-core/lib/middleman-core/templates/extension/Gemfile | 1 - .../lib/middleman-core/templates/extension/Rakefile | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index 28cc9224..24ba43b2 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,6 @@ gem 'yard', '~> 0.8', require: false gem 'pry', '~> 0.10', group: :development gem 'aruba', '~> 0.7.4' gem 'rspec', '~> 3.0' -gem 'fivemat', '~> 1.3' gem 'cucumber', '~> 2.0' # Optional middleman dependencies, included for tests diff --git a/gem_rake_helper.rb b/gem_rake_helper.rb index a90ea7dc..ff7a592d 100644 --- a/gem_rake_helper.rb +++ b/gem_rake_helper.rb @@ -21,7 +21,7 @@ Cucumber::Rake::Task.new do |t| exempt_tags << '--tags ~@encoding' unless Object.const_defined?(:Encoding) exempt_tags << '--tags ~@nowindows' if Gem.win_platform? exempt_tags << '--tags ~@travishatesme' if ENV['TRAVIS'] == 'true' - t.cucumber_opts = "--require features --color #{exempt_tags.join(' ')} --strict --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}" + t.cucumber_opts = "--require features --color #{exempt_tags.join(' ')} --strict"# --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}" end Cucumber::Rake::Task.new(:cucumber_wip) do |t| @@ -29,7 +29,7 @@ Cucumber::Rake::Task.new(:cucumber_wip) do |t| exempt_tags << '--tags ~@nojava' if RUBY_PLATFORM == 'java' exempt_tags << '--tags ~@encoding' unless Object.const_defined?(:Encoding) exempt_tags << '--tags ~@nowindows' if Gem.win_platform? - t.cucumber_opts = "--color #{exempt_tags.join(' ')} --strict --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}" + t.cucumber_opts = "--color #{exempt_tags.join(' ')} --strict"# --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}" end require 'rspec/core/rake_task' diff --git a/middleman-core/lib/middleman-core/templates/extension/Gemfile b/middleman-core/lib/middleman-core/templates/extension/Gemfile index 81495fe1..b52f3729 100644 --- a/middleman-core/lib/middleman-core/templates/extension/Gemfile +++ b/middleman-core/lib/middleman-core/templates/extension/Gemfile @@ -13,7 +13,6 @@ end group :test do gem 'cucumber' - gem 'fivemat' gem 'aruba' gem 'rspec' end diff --git a/middleman-core/lib/middleman-core/templates/extension/Rakefile b/middleman-core/lib/middleman-core/templates/extension/Rakefile index 7910cf22..529dfacf 100644 --- a/middleman-core/lib/middleman-core/templates/extension/Rakefile +++ b/middleman-core/lib/middleman-core/templates/extension/Rakefile @@ -4,7 +4,7 @@ Bundler::GemHelper.install_tasks require 'cucumber/rake/task' Cucumber::Rake::Task.new(:cucumber, 'Run features that should pass') do |t| - t.cucumber_opts = "--color --tags ~@wip --strict --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}" + t.cucumber_opts = "--color --tags ~@wip --strict" end require 'rake/clean' From 8cce9b8a8cf465c5de9b663e99598b0c4e70b900 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 10 Aug 2015 10:00:23 -0700 Subject: [PATCH 084/364] Loudly announce external pipeline errors and exit with failure. --- .../lib/middleman-core/extensions/external_pipeline.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/middleman-core/lib/middleman-core/extensions/external_pipeline.rb b/middleman-core/lib/middleman-core/extensions/external_pipeline.rb index 2e4e3669..6fc82aa0 100644 --- a/middleman-core/lib/middleman-core/extensions/external_pipeline.rb +++ b/middleman-core/lib/middleman-core/extensions/external_pipeline.rb @@ -33,5 +33,8 @@ class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension logger.info "== External: #{without_newline}" if without_newline.length > 0 end end + rescue ::Errno::ENOENT => e + logger.error "== External: Command failed with message: #{e.message}" + exit(1) end end From 1a3f96b58fdcb21d40ec4239070337164fbc1195 Mon Sep 17 00:00:00 2001 From: Jim Dalton Date: Mon, 10 Aug 2015 15:04:47 -0700 Subject: [PATCH 085/364] Fix misnamed config value which was causing --force-polling flag to be ignored by file_watcher extension --- .../lib/middleman-core/core_extensions/file_watcher.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 6a800098..617e0ac7 100644 --- a/middleman-core/lib/middleman-core/core_extensions/file_watcher.rb +++ b/middleman-core/lib/middleman-core/core_extensions/file_watcher.rb @@ -30,7 +30,7 @@ module Middleman # Setup source collection. @sources = ::Middleman::Sources.new(app, disable_watcher: app.config[:watcher_disable], - force_polling: app.config[:force_polling], + force_polling: app.config[:watcher_force_polling], latency: app.config[:watcher_latency]) # Add default ignores. From fb6bca234fac2776dc2829230b40645ac37ebaa3 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 10 Aug 2015 16:58:32 -0700 Subject: [PATCH 086/364] Update to newer cucumber and aruba --- Gemfile | 7 ++--- Rakefile | 2 -- gem_rake_helper.rb | 5 ++-- .../middleman-cli/templates/extension/Gemfile | 1 - .../templates/extension/Rakefile | 2 +- .../lib/middleman-core/step_definitions.rb | 1 - .../step_definitions/builder_steps.rb | 16 +++++------ .../step_definitions/middleman_steps.rb | 4 +-- .../step_definitions/server_steps.rb | 28 +++++++++---------- 9 files changed, 30 insertions(+), 36 deletions(-) diff --git a/Gemfile b/Gemfile index 61e9e125..dadde139 100644 --- a/Gemfile +++ b/Gemfile @@ -6,12 +6,9 @@ gem 'yard', '~> 0.8', require: false # Test tools gem 'pry', '~> 0.10', group: :development, require: false -gem 'pry-byebug' -gem 'pry-stack_explorer' -gem 'aruba', '~> 0.6', require: false +gem 'aruba', '~> 0.7.4', require: false gem 'rspec', '~> 3.0', require: false -gem 'fivemat', '~> 1.3', require: false -gem 'cucumber', '~> 1.3', require: false +gem 'cucumber', '~> 2.0', require: false # Optional middleman dependencies, included for tests gem 'haml', '>= 4.0.5', require: false diff --git a/Rakefile b/Rakefile index 8affa54c..09806b6b 100644 --- a/Rakefile +++ b/Rakefile @@ -48,8 +48,6 @@ task :test do GEM_PATHS.each do |g| Dir.chdir("#{File.join(ROOT, g)}") { sh "#{Gem.ruby} -S rake test" } end - - Rake::Task['rubocop'].invoke end desc 'Run specs for all middleman gems' diff --git a/gem_rake_helper.rb b/gem_rake_helper.rb index 5f95c90e..5cc8bb64 100644 --- a/gem_rake_helper.rb +++ b/gem_rake_helper.rb @@ -21,7 +21,7 @@ Cucumber::Rake::Task.new do |t| exempt_tags << '--tags ~@encoding' unless Object.const_defined?(:Encoding) exempt_tags << '--tags ~@nowindows' if Gem.win_platform? exempt_tags << '--tags ~@travishatesme' if ENV['TRAVIS'] == 'true' - t.cucumber_opts = "--color #{exempt_tags.join(' ')} --strict --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}" + t.cucumber_opts = "--require features --color #{exempt_tags.join(' ')} --strict" end Cucumber::Rake::Task.new(:cucumber_wip) do |t| @@ -29,7 +29,8 @@ Cucumber::Rake::Task.new(:cucumber_wip) do |t| exempt_tags << '--tags ~@nojava' if RUBY_PLATFORM == 'java' exempt_tags << '--tags ~@encoding' unless Object.const_defined?(:Encoding) exempt_tags << '--tags ~@nowindows' if Gem.win_platform? - t.cucumber_opts = "--color #{exempt_tags.join(' ')} --strict --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}" + exempt_tags << '--tags ~@travishatesme' if ENV['TRAVIS'] == 'true' + t.cucumber_opts = "--require features --color #{exempt_tags.join(' ')} --strict" end require 'rspec/core/rake_task' diff --git a/middleman-cli/lib/middleman-cli/templates/extension/Gemfile b/middleman-cli/lib/middleman-cli/templates/extension/Gemfile index 81495fe1..b52f3729 100644 --- a/middleman-cli/lib/middleman-cli/templates/extension/Gemfile +++ b/middleman-cli/lib/middleman-cli/templates/extension/Gemfile @@ -13,7 +13,6 @@ end group :test do gem 'cucumber' - gem 'fivemat' gem 'aruba' gem 'rspec' end diff --git a/middleman-cli/lib/middleman-cli/templates/extension/Rakefile b/middleman-cli/lib/middleman-cli/templates/extension/Rakefile index 7910cf22..529dfacf 100644 --- a/middleman-cli/lib/middleman-cli/templates/extension/Rakefile +++ b/middleman-cli/lib/middleman-cli/templates/extension/Rakefile @@ -4,7 +4,7 @@ Bundler::GemHelper.install_tasks require 'cucumber/rake/task' Cucumber::Rake::Task.new(:cucumber, 'Run features that should pass') do |t| - t.cucumber_opts = "--color --tags ~@wip --strict --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}" + t.cucumber_opts = "--color --tags ~@wip --strict" end require 'rake/clean' diff --git a/middleman-core/lib/middleman-core/step_definitions.rb b/middleman-core/lib/middleman-core/step_definitions.rb index 083bca0a..1c648164 100644 --- a/middleman-core/lib/middleman-core/step_definitions.rb +++ b/middleman-core/lib/middleman-core/step_definitions.rb @@ -1,5 +1,4 @@ require 'aruba/cucumber' -require 'aruba/jruby' require 'middleman-core/step_definitions/middleman_steps' require 'middleman-core/step_definitions/builder_steps' require 'middleman-core/step_definitions/server_steps' diff --git a/middleman-core/lib/middleman-core/step_definitions/builder_steps.rb b/middleman-core/lib/middleman-core/step_definitions/builder_steps.rb index 47292862..3293c082 100644 --- a/middleman-core/lib/middleman-core/step_definitions/builder_steps.rb +++ b/middleman-core/lib/middleman-core/step_definitions/builder_steps.rb @@ -6,8 +6,8 @@ end Given /^app "([^\"]*)" is using config "([^\"]*)"$/ do |path, config_name| target = File.join(PROJECT_ROOT_PATH, 'fixtures', path) - config_path = File.join(current_dir, "config-#{config_name}.rb") - config_dest = File.join(current_dir, 'config.rb') + config_path = File.join(expand_path("."), "config-#{config_name}.rb") + config_dest = File.join(expand_path("."), 'config.rb') FileUtils.cp(config_path, config_dest) end @@ -22,12 +22,12 @@ Given /^a fixture app "([^\"]*)"$/ do |path| # This step can be reentered from several places but we don't want # to keep re-copying and re-cd-ing into ever-deeper directories - next if File.basename(current_dir) == path + next if File.basename(expand_path(".")) == path step %Q{a directory named "#{path}"} target_path = File.join(PROJECT_ROOT_PATH, 'fixtures', path) - FileUtils.cp_r(target_path, current_dir) + FileUtils.cp_r(target_path, expand_path(".")) step %Q{I cd to "#{path}"} end @@ -58,20 +58,20 @@ Given /^a successfully built app at "([^\"]*)" with flags "([^\"]*)"$/ do |path, end Given /^a modification time for a file named "([^\"]*)"$/ do |file| - target = File.join(current_dir, file) + target = File.join(expand_path("."), file) @modification_times[target] = File.mtime(target) end Then /^the file "([^\"]*)" should not have been updated$/ do |file| - target = File.join(current_dir, file) + target = File.join(expand_path("."), file) expect(File.mtime(target)).to eq(@modification_times[target]) end # Provide this Aruba overload in case we're matching something with quotes in it Then /^the file "([^"]*)" should contain '([^']*)'$/ do |file, partial_content| - check_file_content(file, Regexp.new(Regexp.escape(partial_content)), true) + expect(file).to have_file_content(Regexp.new(Regexp.escape(partial_content)), true) end And /the file "(.*)" should be gzipped/ do |file| - expect(File.binread(File.join(current_dir, file), 2)).to eq(['1F8B'].pack('H*')) + expect(File.binread(File.join(expand_path("."), file), 2)).to eq(['1F8B'].pack('H*')) end diff --git a/middleman-core/lib/middleman-core/step_definitions/middleman_steps.rb b/middleman-core/lib/middleman-core/step_definitions/middleman_steps.rb index f4bed280..395ff3de 100644 --- a/middleman-core/lib/middleman-core/step_definitions/middleman_steps.rb +++ b/middleman-core/lib/middleman-core/step_definitions/middleman_steps.rb @@ -1,7 +1,7 @@ Then /^the file "([^\"]*)" has the contents$/ do |path, contents| write_file(path, contents) - in_current_dir do + cd(".") do @server_inst.files.find_new_files! end end @@ -9,7 +9,7 @@ end Then /^the file "([^\"]*)" is removed$/ do |path| step %Q{I remove the file "#{path}"} - in_current_dir do + cd(".") do @server_inst.files.find_new_files! end end diff --git a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb index 2fbbd3a5..68c3c7d2 100644 --- a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb +++ b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb @@ -31,7 +31,7 @@ Given /^"([^\"]*)" is set to "([^\"]*)"$/ do |variable, value| end Given /^the Server is running$/ do - root_dir = File.expand_path(current_dir) + root_dir = File.expand_path(expand_path(".")) if File.exists?(File.join(root_dir, 'source')) ENV['MM_SOURCE'] = 'source' @@ -43,7 +43,7 @@ Given /^the Server is running$/ do initialize_commands = @initialize_commands || [] - in_current_dir do + cd(".") do @server_inst = ::Middleman::Application.new do config[:watcher_disable] = true config[:show_exceptions] = false @@ -68,13 +68,13 @@ Given /^a template named "([^\"]*)" with:$/ do |name, string| end When /^I go to "([^\"]*)"$/ do |url| - in_current_dir do + cd(".") do @last_response = @browser.get(URI.encode(url)) end end Then /^going to "([^\"]*)" should not raise an exception$/ do |url| - in_current_dir do + cd(".") do last_response = nil expect { last_response = @browser.get(URI.encode(url)) @@ -84,61 +84,61 @@ Then /^going to "([^\"]*)" should not raise an exception$/ do |url| end Then /^the content type should be "([^\"]*)"$/ do |expected| - in_current_dir do + cd(".") do expect(@last_response.content_type).to start_with(expected) end end Then /^I should see "([^\"]*)"$/ do |expected| - in_current_dir do + cd(".") do expect(@last_response.body).to include(expected) end end Then /^I should see '([^\']*)'$/ do |expected| - in_current_dir do + cd(".") do expect(@last_response.body).to include(expected) end end Then /^I should see:$/ do |expected| - in_current_dir do + cd(".") do expect(@last_response.body).to include(expected) end end Then /^I should not see "([^\"]*)"$/ do |expected| - in_current_dir do + cd(".") do expect(@last_response.body).to_not include(expected) end end Then /^I should see content matching %r{(.*)}$/ do |expected| - in_current_dir do + cd(".") do expect(@last_response.body).to match(expected) end end Then /^I should not see content matching %r{(.*)}$/ do |expected| - in_current_dir do + cd(".") do expect(@last_response.body).to_not match(expected) end end Then /^I should not see:$/ do |expected| - in_current_dir do + cd(".") do expect(@browser.last_response.body).to_not include(expected.chomp) end end Then /^the status code should be "([^\"]*)"$/ do |expected| - in_current_dir do + cd(".") do expect(@browser.last_response.status).to eq expected.to_i end end Then /^I should see "([^\"]*)" lines$/ do |lines| - in_current_dir do + cd(".") do expect(@last_response.body.chomp.split($/).length).to eq(lines.to_i) end end From 23cf612dd9d2e323b8bb37724e3412a75d7c63c1 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 12 Aug 2015 10:51:06 -0700 Subject: [PATCH 087/364] bump sprockets branch --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 24ba43b2..08de2a54 100644 --- a/Gemfile +++ b/Gemfile @@ -37,4 +37,4 @@ gem 'coveralls', '~> 0.8', require: false # Middleman itself gem 'middleman', path: 'middleman' gem 'middleman-core', path: 'middleman-core' -gem 'middleman-sprockets', github: 'middleman/middleman-sprockets', branch: 'v3-stable' +gem 'middleman-sprockets', github: 'middleman/middleman-sprockets', branch: 'v3-stable-real' From bb6b8c7f133d2468e5605e7c9624e3221ce32da4 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 12 Aug 2015 15:24:35 -0700 Subject: [PATCH 088/364] Replace Hamster hash for user-accessible data with Hashie Indifferent access --- .../lib/middleman-core/contracts.rb | 10 ---- .../lib/middleman-core/sitemap/resource.rb | 4 +- middleman-core/lib/middleman-core/util.rb | 59 +++++-------------- .../lib/middleman-core/util/data.rb | 2 +- middleman-core/lib/middleman-core/version.rb | 2 +- middleman-core/middleman-core.gemspec | 3 +- .../spec/middleman-core/util_spec.rb | 26 +------- 7 files changed, 23 insertions(+), 83 deletions(-) diff --git a/middleman-core/lib/middleman-core/contracts.rb b/middleman-core/lib/middleman-core/contracts.rb index 16fff201..3afedbfe 100644 --- a/middleman-core/lib/middleman-core/contracts.rb +++ b/middleman-core/lib/middleman-core/contracts.rb @@ -18,16 +18,6 @@ if ENV['TEST'] || ENV['CONTRACTS'] == 'true' end end - class Frozen < CallableClass - def initialize(contract) - @contract = contract - end - - def valid?(val) - (val.frozen? || val.nil? || [::TrueClass, ::FalseClass, ::Fixnum].include?(val.class)) && Contract.valid?(val, @contract) - end - end - VectorOf = Contracts::CollectionOf::Factory.new(::Hamster::Vector) ResourceList = Contracts::ArrayOf[IsA['Middleman::Sitemap::Resource']] end diff --git a/middleman-core/lib/middleman-core/sitemap/resource.rb b/middleman-core/lib/middleman-core/sitemap/resource.rb index 11a085eb..56768900 100644 --- a/middleman-core/lib/middleman-core/sitemap/resource.rb +++ b/middleman-core/lib/middleman-core/sitemap/resource.rb @@ -87,8 +87,8 @@ module Middleman end # Data about this resource, populated from frontmatter or extensions. - # @return [IndifferentHash] - Contract IsA['Middleman::Util::IndifferentHash'] + # @return [Hash] + Contract RespondTo[:indifferent_access?] def data ::Middleman::Util.recursively_enhance(metadata[:page]) end diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index 7d8512f0..bf1f1755 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -11,8 +11,8 @@ require 'rack/mime' # DbC require 'middleman-core/contracts' -# Immutable Data -require 'hamster' +# Indifferent Access +require 'hashie' # For URI templating require 'addressable/uri' @@ -76,56 +76,25 @@ module Middleman end end - class IndifferentHash < ::Hamster::Hash - def [](key) - if key?(key.to_sym) - super(key.to_sym) - elsif key?(key.to_s) - super(key.to_s) - else - super - end - end - - def method_missing(key, *_args) - if key?(key.to_sym) - self[key.to_sym] - elsif key?(key.to_s) - self[key.to_s] - end - end + class EnhancedHash < ::Hash + include ::Hashie::Extensions::MergeInitializer + include ::Hashie::Extensions::MethodReader + include ::Hashie::Extensions::IndifferentAccess end - # Recursively convert a normal Hash into a IndifferentHash + # Recursively convert a normal Hash into a EnhancedHash # # @private # @param [Hash] data Normal hash - # @return [Middleman::Util::IndifferentHash] - FrozenDataStructure = Frozen[Or[IndifferentHash, Array, String, TrueClass, FalseClass, Fixnum, NilClass]] - Contract Maybe[Or[String, Array, Hash, IndifferentHash]] => Maybe[FrozenDataStructure] + # @return [Hash] + Contract Maybe[Hash] => Maybe[Or[Array, EnhancedHash]] def recursively_enhance(obj) - case obj - when ::Hash - res = obj.map { |key, value| [recursively_enhance(key), recursively_enhance(value)] } - IndifferentHash.new(res) - when IndifferentHash - obj.map { |key, value| [recursively_enhance(key), recursively_enhance(value)] } - when ::Array - res = obj.map { |element| recursively_enhance(element) } - Hamster::Vector.new(res) - when ::SortedSet - # This clause must go before ::Set clause, since ::SortedSet is a ::Set. - res = obj.map { |element| recursively_enhance(element) } - Hamster::SortedSet.new(res) - when ::Set - res = obj.map { |element| recursively_enhance(element) } - Hamster::Set.new(res) - when Hamster::Vector, Hamster::Set, Hamster::SortedSet - obj.map { |element| recursively_enhance(element) } - when ::TrueClass, ::FalseClass, ::Fixnum, ::Symbol, ::NilClass, ::Float - obj + if obj.is_a? ::Array + obj.map { |e| recursively_enhance(e) }.freeze + elsif obj.is_a? ::Hash + EnhancedHash.new(obj).freeze else - obj.dup.freeze + obj end end diff --git a/middleman-core/lib/middleman-core/util/data.rb b/middleman-core/lib/middleman-core/util/data.rb index 1d107ef9..a02d64e2 100644 --- a/middleman-core/lib/middleman-core/util/data.rb +++ b/middleman-core/lib/middleman-core/util/data.rb @@ -29,7 +29,7 @@ module Middleman # Get the frontmatter and plain content from a file # @param [String] path - # @return [Array] + # @return [Array] Contract Pathname, Maybe[Symbol] => [Hash, Maybe[String]] def parse(full_path, known_type=nil) data = {} diff --git a/middleman-core/lib/middleman-core/version.rb b/middleman-core/lib/middleman-core/version.rb index 269aebb3..a141218d 100644 --- a/middleman-core/lib/middleman-core/version.rb +++ b/middleman-core/lib/middleman-core/version.rb @@ -1,5 +1,5 @@ module Middleman # Current Version # @return [String] - VERSION = '4.0.0.beta.2' unless const_defined?(:VERSION) + VERSION = '4.0.0.beta.3' unless const_defined?(:VERSION) end diff --git a/middleman-core/middleman-core.gemspec b/middleman-core/middleman-core.gemspec index 752108eb..2078b063 100644 --- a/middleman-core/middleman-core.gemspec +++ b/middleman-core/middleman-core.gemspec @@ -52,6 +52,7 @@ Gem::Specification.new do |s| # Testing s.add_dependency('contracts', ['~> 0.9.0']) - # Immutability + # Hash stuff + s.add_dependency('hashie', ['~> 3.4']) s.add_dependency('hamster', ['~> 1.0']) end diff --git a/middleman-core/spec/middleman-core/util_spec.rb b/middleman-core/spec/middleman-core/util_spec.rb index f339a31c..447d1abd 100644 --- a/middleman-core/spec/middleman-core/util_spec.rb +++ b/middleman-core/spec/middleman-core/util_spec.rb @@ -54,43 +54,23 @@ describe Middleman::Util do end describe "::recursively_enhance" do - it "returns IndifferentHash if given one" do - input = Middleman::Util::IndifferentHash.new({test: "subject"}) - subject = Middleman::Util.recursively_enhance input - - expect( subject ).to be_a Middleman::Util::IndifferentHash - expect( subject.test ).to eq "subject" - end - - it "returns IndifferentHash if given a hash" do + it "returns Hashie extended Hash if given a hash" do input = {test: "subject"} subject = Middleman::Util.recursively_enhance input - - expect( subject ).to be_a Middleman::Util::IndifferentHash + expect( subject.test ).to eq "subject" end it "returns Array with strings, or IndifferentHash, true, false" do - indifferent_hash = Middleman::Util::IndifferentHash.new({test: "subject"}) + indifferent_hash = {test: "subject"} regular_hash = {regular: "hash"} input = [ indifferent_hash, regular_hash, true, false ] subject = Middleman::Util.recursively_enhance input - expect( subject[0] ).to be_a Middleman::Util::IndifferentHash - expect( subject[1] ).to be_a Middleman::Util::IndifferentHash expect( subject[1].regular ).to eq "hash" expect( subject[2] ).to eq true expect( subject[3] ).to eq false end - - it "returns duplicated & frozen original object if not special cased" do - input = "foo" - subject = Middleman::Util.recursively_enhance input - - expect( subject ).to eq input - expect( subject.object_id ).not_to eq input.object_id - expect( subject ).to be_frozen - end end end \ No newline at end of file From 50bf848ee8f77d5ea5f7aa419108b2ba3dba2dc4 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 17 Aug 2015 10:48:56 -0700 Subject: [PATCH 089/364] Add config CLI command --- middleman-cli/lib/middleman-cli.rb | 1 + middleman-cli/lib/middleman-cli/config.rb | 33 +++++++++++++++++++ .../middleman-core/extensions/asset_hash.rb | 1 + 3 files changed, 35 insertions(+) create mode 100644 middleman-cli/lib/middleman-cli/config.rb diff --git a/middleman-cli/lib/middleman-cli.rb b/middleman-cli/lib/middleman-cli.rb index 67565f3e..83b95d30 100644 --- a/middleman-cli/lib/middleman-cli.rb +++ b/middleman-cli/lib/middleman-cli.rb @@ -31,3 +31,4 @@ require 'middleman-cli/extension' require 'middleman-cli/server' require 'middleman-cli/build' require 'middleman-cli/console' +require 'middleman-cli/config' diff --git a/middleman-cli/lib/middleman-cli/config.rb b/middleman-cli/lib/middleman-cli/config.rb new file mode 100644 index 00000000..b5b64064 --- /dev/null +++ b/middleman-cli/lib/middleman-cli/config.rb @@ -0,0 +1,33 @@ +# CLI Module +module Middleman::Cli + # The CLI Config class + class Config < Thor::Group + include Thor::Actions + + check_unknown_options! + + class_option :environment, + aliases: '-e', + default: ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development', + desc: 'The environment Middleman will run under' + def console + require 'json' + require 'middleman-core' + + opts = { + environment: options['environment'] + } + + app = ::Middleman::Application.new do + config[:environment] = opts[:environment].to_sym if opts[:environment] + end + + puts JSON.pretty_generate(app.config.to_h) + + app.shutdown! + end + + # Add to CLI + Base.register(self, 'config', 'config [options]', 'Output a Middleman configuration in JSON format') + end +end diff --git a/middleman-core/lib/middleman-core/extensions/asset_hash.rb b/middleman-core/lib/middleman-core/extensions/asset_hash.rb index 07d58234..bb1389e9 100644 --- a/middleman-core/lib/middleman-core/extensions/asset_hash.rb +++ b/middleman-core/lib/middleman-core/extensions/asset_hash.rb @@ -1,5 +1,6 @@ require 'addressable/uri' require 'middleman-core/util' +require 'middleman-core/rack' class Middleman::Extensions::AssetHash < ::Middleman::Extension option :exts, %w(.jpg .jpeg .png .gif .webp .js .css .otf .woff .woff2 .eot .ttf .svg), 'List of extensions that get asset hashes appended to them.' From 226099d64e8ec8a4dbf23f13c48034147b580653 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 17 Aug 2015 10:55:34 -0700 Subject: [PATCH 090/364] Bump listen for test --- middleman-core/middleman-core.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/middleman-core.gemspec b/middleman-core/middleman-core.gemspec index 2078b063..02952f07 100644 --- a/middleman-core/middleman-core.gemspec +++ b/middleman-core/middleman-core.gemspec @@ -31,7 +31,7 @@ Gem::Specification.new do |s| s.add_dependency("addressable", ["~> 2.3.5"]) # Watcher - s.add_dependency('listen', ['>= 2.7.9', '< 3.0']) + s.add_dependency('listen', ['~> 3.0']) # i18n s.add_dependency('i18n', ['~> 0.7.0']) From 9886e04a95ef0eb4afac33f188e67526cbe312ee Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 17 Aug 2015 14:28:15 -0700 Subject: [PATCH 091/364] Patch around seemingly invalid logic in Listen v3 --- .../lib/middleman-core/preview_server.rb | 5 +++- .../middleman-core/sources/source_watcher.rb | 27 ++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/middleman-core/lib/middleman-core/preview_server.rb b/middleman-core/lib/middleman-core/preview_server.rb index 073864a2..9aa0af86 100644 --- a/middleman-core/lib/middleman-core/preview_server.rb +++ b/middleman-core/lib/middleman-core/preview_server.rb @@ -124,9 +124,12 @@ module Middleman ] # config.rb - files.watch :reload, + watcher = files.watch :reload, path: root, only: match_against + + # Hack around node_modules in root. + watcher.listener.ignore(/^node_modules/) end end diff --git a/middleman-core/lib/middleman-core/sources/source_watcher.rb b/middleman-core/lib/middleman-core/sources/source_watcher.rb index 80b3702f..82dc8f74 100644 --- a/middleman-core/lib/middleman-core/sources/source_watcher.rb +++ b/middleman-core/lib/middleman-core/sources/source_watcher.rb @@ -4,6 +4,26 @@ require 'middleman-core/contracts' require 'middleman-core/contracts' require 'backports/2.0.0/enumerable/lazy' +# Monkey patch Listen silencer so `only` works on directories too +module Listen + class Silencer + # TODO: switch type and path places - and verify + def silenced?(relative_path, type) + path = relative_path.to_s + + # if only_patterns && type == :file + # return true unless only_patterns.any? { |pattern| path =~ pattern } + # end + + if only_patterns + return !only_patterns.any? { |pattern| path =~ pattern } + end + + ignore_patterns.any? { |pattern| path =~ pattern } + end + end +end + module Middleman # The default source watcher implementation. Watches a directory on disk # and responds to events on changes. @@ -29,6 +49,9 @@ module Middleman Contract Hash attr_reader :options + # Reference to lower level listener + attr_reader :listener + # Construct a new SourceWatcher # # @param [Middleman::Sources] parent The parent collection. @@ -138,9 +161,11 @@ module Middleman config[:latency] = @latency if @latency @listener = ::Listen.to(@directory.to_s, config, &method(:on_listener_change)) - @listener.start + @listener.ignore(/^\.sass-cache/) @listener.only(@only) unless @only.empty? + + @listener.start end # Stop the listener. From 241fe69f7de8cd230311c4ba70dfbcab485f1cd9 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 17 Aug 2015 14:33:19 -0700 Subject: [PATCH 092/364] Adding ignore --- middleman-core/lib/middleman-core/preview_server.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/middleman-core/lib/middleman-core/preview_server.rb b/middleman-core/lib/middleman-core/preview_server.rb index 9aa0af86..175ad4d2 100644 --- a/middleman-core/lib/middleman-core/preview_server.rb +++ b/middleman-core/lib/middleman-core/preview_server.rb @@ -130,6 +130,9 @@ module Middleman # Hack around node_modules in root. watcher.listener.ignore(/^node_modules/) + + # Hack around sass cache in root. + watcher.listener.ignore(/^\.sass-cache/) end end From 0861fad2e1a464494d73336a327b8b71acc6a7e7 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 17 Aug 2015 15:59:48 -0700 Subject: [PATCH 093/364] Adding ignore --- middleman-core/lib/middleman-core/preview_server.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/middleman-core/lib/middleman-core/preview_server.rb b/middleman-core/lib/middleman-core/preview_server.rb index 175ad4d2..4d727bd1 100644 --- a/middleman-core/lib/middleman-core/preview_server.rb +++ b/middleman-core/lib/middleman-core/preview_server.rb @@ -133,6 +133,9 @@ module Middleman # Hack around sass cache in root. watcher.listener.ignore(/^\.sass-cache/) + + # Hack around bundler cache in root. + watcher.listener.ignore(/^vendor\/bundle/) end end From 3485f49f74bddd65470836e9aa3e5f59e26351a6 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 18 Aug 2015 16:22:32 -0700 Subject: [PATCH 094/364] Use Hashie Mash for recursive indifferent --- middleman-core/lib/middleman-core/util.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index bf1f1755..a444617e 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -76,10 +76,10 @@ module Middleman end end - class EnhancedHash < ::Hash - include ::Hashie::Extensions::MergeInitializer - include ::Hashie::Extensions::MethodReader - include ::Hashie::Extensions::IndifferentAccess + class EnhancedHash < ::Hashie::Mash + # include ::Hashie::Extensions::MergeInitializer + # include ::Hashie::Extensions::MethodReader + # include ::Hashie::Extensions::IndifferentAccess end # Recursively convert a normal Hash into a EnhancedHash @@ -90,9 +90,9 @@ module Middleman Contract Maybe[Hash] => Maybe[Or[Array, EnhancedHash]] def recursively_enhance(obj) if obj.is_a? ::Array - obj.map { |e| recursively_enhance(e) }.freeze + obj.map { |e| recursively_enhance(e) } elsif obj.is_a? ::Hash - EnhancedHash.new(obj).freeze + ::Hashie::Mash.new(obj) else obj end From 9ed0796b4a346af3228d6cf880081f04ca6dc159 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Thu, 20 Aug 2015 17:45:18 -0700 Subject: [PATCH 095/364] Move some extension setup to ready event --- middleman-cli/lib/middleman-cli/config.rb | 5 +++++ middleman-core/lib/middleman-core/application.rb | 6 +++++- .../lib/middleman-core/core_extensions/show_exceptions.rb | 2 +- middleman-core/lib/middleman-core/extensions/asset_hash.rb | 2 +- middleman-core/lib/middleman-core/extensions/asset_host.rb | 2 +- .../lib/middleman-core/extensions/external_pipeline.rb | 2 +- middleman-core/lib/middleman-core/extensions/minify_css.rb | 2 +- .../lib/middleman-core/extensions/minify_javascript.rb | 2 +- .../lib/middleman-core/extensions/relative_assets.rb | 2 +- 9 files changed, 17 insertions(+), 8 deletions(-) diff --git a/middleman-cli/lib/middleman-cli/config.rb b/middleman-cli/lib/middleman-cli/config.rb index b5b64064..902ea216 100644 --- a/middleman-cli/lib/middleman-cli/config.rb +++ b/middleman-cli/lib/middleman-cli/config.rb @@ -13,12 +13,17 @@ module Middleman::Cli def console require 'json' require 'middleman-core' + require 'middleman-core/logger' opts = { environment: options['environment'] } + # Don't output info messages + ::Middleman::Logger.singleton(2, false) + app = ::Middleman::Application.new do + config[:exit_before_ready] = true config[:environment] = opts[:environment].to_sym if opts[:environment] end diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index 9d8a239d..ecd863f2 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -92,6 +92,10 @@ module Middleman # @return [String] define_setting :source, 'source', 'Name of the source directory' + # If we should exit before ready event. + # @return [Boolean] + define_setting :exit_before_ready, false, 'If we should exit before ready event.' + # Middleman mode. Defaults to :server, set to :build by the build process # @return [String] define_setting :mode, ((ENV['MM_ENV'] && ENV['MM_ENV'].to_sym) || :server), 'Middleman mode. Defaults to :server' @@ -274,7 +278,7 @@ module Middleman execute_callbacks(:after_configuration) # Everything is stable - execute_callbacks(:ready) + execute_callbacks(:ready) unless config[:exit_before_ready] end # Eval config diff --git a/middleman-core/lib/middleman-core/core_extensions/show_exceptions.rb b/middleman-core/lib/middleman-core/core_extensions/show_exceptions.rb index 6f01448a..b6407100 100644 --- a/middleman-core/lib/middleman-core/core_extensions/show_exceptions.rb +++ b/middleman-core/lib/middleman-core/core_extensions/show_exceptions.rb @@ -11,7 +11,7 @@ module Middleman::CoreExtensions app.config.define_setting :show_exceptions, ENV['TEST'] ? false : true, 'Whether to catch and display exceptions' end - def after_configuration + def ready app.use ::Rack::ShowExceptions if !app.build? && app.config[:show_exceptions] end end diff --git a/middleman-core/lib/middleman-core/extensions/asset_hash.rb b/middleman-core/lib/middleman-core/extensions/asset_hash.rb index bb1389e9..e3248bd5 100644 --- a/middleman-core/lib/middleman-core/extensions/asset_hash.rb +++ b/middleman-core/lib/middleman-core/extensions/asset_hash.rb @@ -17,7 +17,7 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension def after_configuration # Allow specifying regexes to ignore, plus always ignore apple touch icons @ignore = Array(options.ignore) + [/^apple-touch-icon/] - + app.use ::Middleman::Middleware::InlineURLRewriter, id: :asset_hash, url_extensions: options.exts, diff --git a/middleman-core/lib/middleman-core/extensions/asset_host.rb b/middleman-core/lib/middleman-core/extensions/asset_host.rb index 79e1813d..d0487591 100644 --- a/middleman-core/lib/middleman-core/extensions/asset_host.rb +++ b/middleman-core/lib/middleman-core/extensions/asset_host.rb @@ -7,7 +7,7 @@ class Middleman::Extensions::AssetHost < ::Middleman::Extension option :sources, %w(.htm .html .php .css .js), 'List of extensions that are searched for bustable assets.' option :ignore, [], 'Regexes of filenames to skip adding query strings to' - def after_configuration + def ready app.use ::Middleman::Middleware::InlineURLRewriter, id: :asset_host, url_extensions: options.exts, diff --git a/middleman-core/lib/middleman-core/extensions/external_pipeline.rb b/middleman-core/lib/middleman-core/extensions/external_pipeline.rb index 6fc82aa0..9c649f5e 100644 --- a/middleman-core/lib/middleman-core/extensions/external_pipeline.rb +++ b/middleman-core/lib/middleman-core/extensions/external_pipeline.rb @@ -16,7 +16,7 @@ class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension latency: options[:latency] end - def after_configuration + def ready if app.build? logger.info "== Executing: `#{options[:command]}`" watch_command! diff --git a/middleman-core/lib/middleman-core/extensions/minify_css.rb b/middleman-core/lib/middleman-core/extensions/minify_css.rb index 75b2ca4b..df7d7567 100644 --- a/middleman-core/lib/middleman-core/extensions/minify_css.rb +++ b/middleman-core/lib/middleman-core/extensions/minify_css.rb @@ -9,7 +9,7 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension SassCompressor }, 'Set the CSS compressor to use.' - def after_configuration + def ready # Setup Rack middleware to minify CSS app.use Rack, compressor: options[:compressor], ignore: Array(options[:ignore]) + [/\.min\./], diff --git a/middleman-core/lib/middleman-core/extensions/minify_javascript.rb b/middleman-core/lib/middleman-core/extensions/minify_javascript.rb index 5c90bd13..466fb133 100644 --- a/middleman-core/lib/middleman-core/extensions/minify_javascript.rb +++ b/middleman-core/lib/middleman-core/extensions/minify_javascript.rb @@ -9,7 +9,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension ::Uglifier.new }, 'Set the JS compressor to use.' - def after_configuration + def ready # Setup Rack middleware to minify CSS app.use Rack, compressor: options[:compressor], ignore: Array(options[:ignore]) + [/\.min\./], diff --git a/middleman-core/lib/middleman-core/extensions/relative_assets.rb b/middleman-core/lib/middleman-core/extensions/relative_assets.rb index 58ba20c3..74d7d180 100644 --- a/middleman-core/lib/middleman-core/extensions/relative_assets.rb +++ b/middleman-core/lib/middleman-core/extensions/relative_assets.rb @@ -12,7 +12,7 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension require 'middleman-core/middleware/inline_url_rewriter' end - def after_configuration + def ready app.use ::Middleman::Middleware::InlineURLRewriter, id: :asset_hash, url_extensions: options.exts, From f76561d1012d6fdfb2120479b9238249a52bff22 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Fri, 28 Aug 2015 09:58:10 -0700 Subject: [PATCH 096/364] Add logger require in rack. Addresses #1550 --- middleman-core/lib/middleman-core/rack.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/middleman-core/lib/middleman-core/rack.rb b/middleman-core/lib/middleman-core/rack.rb index 8f6b1609..583056de 100644 --- a/middleman-core/lib/middleman-core/rack.rb +++ b/middleman-core/lib/middleman-core/rack.rb @@ -4,6 +4,7 @@ require 'rack/lint' require 'rack/head' require 'middleman-core/util' +require 'middleman-core/logger' require 'middleman-core/template_renderer' # CSSPIE HTC File From 8bdeab50eeb5d3fce4ac76b6d84f2f112a068eb6 Mon Sep 17 00:00:00 2001 From: Brad Gessler Date: Fri, 28 Aug 2015 13:08:56 -0700 Subject: [PATCH 097/364] Fix typo in server CLI. --- middleman-core/lib/middleman-core/cli/server.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/cli/server.rb b/middleman-core/lib/middleman-core/cli/server.rb index 8c7d0d06..cda9373c 100644 --- a/middleman-core/lib/middleman-core/cli/server.rb +++ b/middleman-core/lib/middleman-core/cli/server.rb @@ -16,7 +16,7 @@ module Middleman::Cli desc: 'The port Middleman will listen on' method_option :server_name, aliases: '-s', - desc: 'The server name name Middleman will use' + desc: 'The server name Middleman will use' method_option :bind_address, aliases: '-b', desc: 'The bind address Middleman will listen on' From 5cab7c46a9dc411d46142915866a293f7ba9f431 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 31 Aug 2015 11:18:45 -0700 Subject: [PATCH 098/364] Store intermediate resources in reducer so the array is not empty the first run. Addresses #1590 --- middleman-core/lib/middleman-core/sitemap/store.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/middleman-core/lib/middleman-core/sitemap/store.rb b/middleman-core/lib/middleman-core/sitemap/store.rb index a5541349..aa46497b 100644 --- a/middleman-core/lib/middleman-core/sitemap/store.rb +++ b/middleman-core/lib/middleman-core/sitemap/store.rb @@ -211,20 +211,21 @@ module Middleman @app.logger.debug '== Rebuilding resource list' - @resources = @resource_list_manipulators.reduce([]) do |result, (_, inst)| - newres = inst.manipulate_resource_list(result) + @resources = [] + + @resource_list_manipulators.each do |(_, inst)| + @resources = inst.manipulate_resource_list(@resources) # Reset lookup cache reset_lookup_cache! - newres.each do |resource| + + @resources.each do |resource| @_lookup_by_path[resource.path] = resource @_lookup_by_destination_path[resource.destination_path] = resource end - newres + invalidate_resources_not_ignored_cache! end - - invalidate_resources_not_ignored_cache! end end From 7a28fd0a508d34dfa4a37cc181e0d1c7656b5b72 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 31 Aug 2015 11:25:22 -0700 Subject: [PATCH 099/364] disable osx builds for now --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 71acb01f..7bc8a3be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ rvm: - 1.9.3 os: - linux - - osx + # - osx cache: bundler sudo: false matrix: From d849930e511b7eb102d8b370d7fdf792ef3e50b6 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Tue, 1 Sep 2015 09:58:13 -0700 Subject: [PATCH 100/364] Don't set mode AND environment with the same ENV --- middleman-core/lib/middleman-core/application.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index ecd863f2..9ee3f4b9 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -98,11 +98,11 @@ module Middleman # Middleman mode. Defaults to :server, set to :build by the build process # @return [String] - define_setting :mode, ((ENV['MM_ENV'] && ENV['MM_ENV'].to_sym) || :server), 'Middleman mode. Defaults to :server' + define_setting :mode, :server, 'Middleman mode. Defaults to :server' # Middleman environment. Defaults to :development # @return [String] - define_setting :environment, :development, 'Middleman environment. Defaults to :development' + define_setting :environment, ((ENV['MM_ENV'] && ENV['MM_ENV'].to_sym) || :development), 'Middleman environment. Defaults to :development' # Which file should be used for directory indexes # @return [String] From 0d4d82a01a0067b39c9215f955fdaa38227eac82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Komorowski?= Date: Thu, 3 Sep 2015 18:25:43 +0200 Subject: [PATCH 101/364] Update middleman-livereload version to more current As discussed https://github.com/middleman/middleman-livereload/issues/69 but I forgot to apply the fix to source code inside MM. @tdreyno, should it be `~> 3.3.0` or `~> 3.4.0`? I looked into 3.4 changes and they seem to be MM v4 related? --- middleman-core/lib/middleman-core/templates/shared/Gemfile.tt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/middleman-core/lib/middleman-core/templates/shared/Gemfile.tt b/middleman-core/lib/middleman-core/templates/shared/Gemfile.tt index 50d76543..e4c03d0d 100644 --- a/middleman-core/lib/middleman-core/templates/shared/Gemfile.tt +++ b/middleman-core/lib/middleman-core/templates/shared/Gemfile.tt @@ -5,10 +5,10 @@ source 'https://rubygems.org' gem "middleman", "~><%= Middleman::VERSION %>" # Live-reloading plugin -gem "middleman-livereload", "~> 3.1.0" +gem "middleman-livereload", "~> 3.3.0" # For faster file watcher updates on Windows: gem "wdm", "~> 0.1.0", :platforms => [:mswin, :mingw] # Windows does not come with time zone data -gem "tzinfo-data", platforms: [:mswin, :mingw, :jruby] \ No newline at end of file +gem "tzinfo-data", platforms: [:mswin, :mingw, :jruby] From 441dc2faa68822ed06f09cdc9105a7256a3da7d4 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 9 Sep 2015 11:55:56 -0700 Subject: [PATCH 102/364] Revert breaking resource source_file api. For #1595 --- middleman-core/features/collections.feature | 2 +- .../frontmatter-neighbor-app/config.rb | 4 +- .../config.rb | 6 +-- .../more-traversal-app/source/layout.erb | 2 +- .../fixtures/traversal-app/source/layout.erb | 2 +- middleman-core/lib/middleman-core/builder.rb | 2 +- .../core_extensions/front_matter.rb | 4 +- .../meta_pages/sitemap_resource.rb | 2 +- middleman-core/lib/middleman-core/rack.rb | 2 +- .../lib/middleman-core/renderers/liquid.rb | 4 +- .../sitemap/extensions/proxies.rb | 6 +-- .../lib/middleman-core/sitemap/resource.rb | 37 +++++++++++-------- .../lib/middleman-core/template_context.rb | 4 +- 13 files changed, 42 insertions(+), 35 deletions(-) diff --git a/middleman-core/features/collections.feature b/middleman-core/features/collections.feature index 30f32691..a745a5a1 100644 --- a/middleman-core/features/collections.feature +++ b/middleman-core/features/collections.feature @@ -98,7 +98,7 @@ Feature: Collections And a file named "source/index.html.erb" with: """ <% collection(:articles).each do |article| %> - Article: <%= article.data.title || article.source_file[:relative_path] %> + Article: <%= article.data.title || article.file_descriptor[:relative_path] %> <% end %> """ Given the Server is running at "collections-app" diff --git a/middleman-core/fixtures/frontmatter-neighbor-app/config.rb b/middleman-core/fixtures/frontmatter-neighbor-app/config.rb index babfbc2c..b9f82b36 100644 --- a/middleman-core/fixtures/frontmatter-neighbor-app/config.rb +++ b/middleman-core/fixtures/frontmatter-neighbor-app/config.rb @@ -7,9 +7,9 @@ class NeighborFrontmatter < ::Middleman::Extension def manipulate_resource_list(resources) resources.each do |resource| - next unless resource.source_file + next unless resource.file_descriptor - neighbor = "#{resource.source_file[:relative_path]}.frontmatter" + neighbor = "#{resource.file_descriptor[:relative_path]}.frontmatter" file = app.files.find(:source, neighbor) diff --git a/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb b/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb index 1fc88608..93cd8f1f 100644 --- a/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb +++ b/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb @@ -12,12 +12,12 @@ class NeighborFrontmatter < ::Middleman::Extension def manipulate_resource_list(resources) resources.each do |resource| - next unless resource.source_file - next if resource.source_file[:relative_path].extname == '.frontmatter' + next unless resource.file_descriptor + next if resource.file_descriptor[:relative_path].extname == '.frontmatter' [ "#{resource.url.sub(/^\//, '')}.frontmatter", - "#{resource.source_file[:relative_path]}.frontmatter" + "#{resource.file_descriptor[:relative_path]}.frontmatter" ].each do |n| file = app.files.find(:source, n) apply_neighbor_data(resource, file) if file diff --git a/middleman-core/fixtures/more-traversal-app/source/layout.erb b/middleman-core/fixtures/more-traversal-app/source/layout.erb index 25411d39..f0aea54a 100644 --- a/middleman-core/fixtures/more-traversal-app/source/layout.erb +++ b/middleman-core/fixtures/more-traversal-app/source/layout.erb @@ -1,6 +1,6 @@ Path: <%= current_page.path %> -Source: <%= current_page.source_file[:full_path].sub(root + "/", "") %> +Source: <%= current_page.file_descriptor[:full_path].sub(root + "/", "") %> <% if current_page.parent %> Parent: <%= current_page.parent.path %> diff --git a/middleman-core/fixtures/traversal-app/source/layout.erb b/middleman-core/fixtures/traversal-app/source/layout.erb index 25411d39..f0aea54a 100644 --- a/middleman-core/fixtures/traversal-app/source/layout.erb +++ b/middleman-core/fixtures/traversal-app/source/layout.erb @@ -1,6 +1,6 @@ Path: <%= current_page.path %> -Source: <%= current_page.source_file[:full_path].sub(root + "/", "") %> +Source: <%= current_page.file_descriptor[:full_path].sub(root + "/", "") %> <% if current_page.parent %> Parent: <%= current_page.parent.path %> diff --git a/middleman-core/lib/middleman-core/builder.rb b/middleman-core/lib/middleman-core/builder.rb index 0d0966c4..e386c2d0 100644 --- a/middleman-core/lib/middleman-core/builder.rb +++ b/middleman-core/lib/middleman-core/builder.rb @@ -169,7 +169,7 @@ module Middleman begin if resource.binary? - export_file!(output_file, resource.source_file[:full_path]) + export_file!(output_file, resource.file_descriptor[:full_path]) else response = @rack.get(URI.escape(resource.request_path)) 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 0e26259a..03d2f431 100644 --- a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb @@ -28,9 +28,9 @@ module Middleman::CoreExtensions Contract ResourceList => ResourceList def manipulate_resource_list(resources) resources.each do |resource| - next if resource.source_file.nil? + next if resource.file_descriptor.nil? - fmdata = data(resource.source_file[:full_path].to_s).first.dup + fmdata = data(resource.file_descriptor[:full_path].to_s).first.dup # Copy over special options # TODO: Should we make people put these under "options" instead of having diff --git a/middleman-core/lib/middleman-core/meta_pages/sitemap_resource.rb b/middleman-core/lib/middleman-core/meta_pages/sitemap_resource.rb index a42f9157..d746be95 100644 --- a/middleman-core/lib/middleman-core/meta_pages/sitemap_resource.rb +++ b/middleman-core/lib/middleman-core/meta_pages/sitemap_resource.rb @@ -39,7 +39,7 @@ module Middleman build_path = 'Not built' if ignored? props['Build Path'] = build_path if @resource.path != build_path props['URL'] = content_tag(:a, @resource.url, href: @resource.url) unless ignored? - props['Source File'] = @resource.source_file ? @resource.source_file[:full_path].to_s.sub(/^#{Regexp.escape(ENV['MM_ROOT'] + '/')}/, '') : 'Dynamic' + props['Source File'] = @resource.file_descriptor ? @resource.file_descriptor[:full_path].to_s.sub(/^#{Regexp.escape(ENV['MM_ROOT'] + '/')}/, '') : 'Dynamic' data = @resource.data props['Data'] = data.inspect unless data.empty? diff --git a/middleman-core/lib/middleman-core/rack.rb b/middleman-core/lib/middleman-core/rack.rb index 583056de..a6743c59 100644 --- a/middleman-core/lib/middleman-core/rack.rb +++ b/middleman-core/lib/middleman-core/rack.rb @@ -126,7 +126,7 @@ module Middleman # Immediately send static file def send_file(resource, env) file = ::Rack::File.new nil - file.path = resource.source_file[:full_path] + file.path = resource.file_descriptor[:full_path] response = file.serving(env) status = response[0] response[1]['Content-Encoding'] = 'gzip' if %w(.svgz .gz).include?(resource.ext) diff --git a/middleman-core/lib/middleman-core/renderers/liquid.rb b/middleman-core/lib/middleman-core/renderers/liquid.rb index e09306b4..daa7d220 100644 --- a/middleman-core/lib/middleman-core/renderers/liquid.rb +++ b/middleman-core/lib/middleman-core/renderers/liquid.rb @@ -23,8 +23,8 @@ module Middleman return resources unless app.extensions[:data] resources.each do |resource| - next if resource.source_file.nil? - next unless resource.source_file[:relative_path].to_s =~ %r{\.liquid$} + next if resource.file_descriptor.nil? + next unless resource.file_descriptor[:relative_path].to_s =~ %r{\.liquid$} # Convert data object into a hash for liquid resource.add_metadata locals: { diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb index 0ad0a512..78d6e17a 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb @@ -87,7 +87,7 @@ module Middleman # Initialize resource with parent store and URL # @param [Middleman::Sitemap::Store] store # @param [String] path - # @param [String] source_file + # @param [String] target def initialize(store, path, target) super(store, path) @@ -115,8 +115,8 @@ module Middleman end Contract IsA['Middleman::SourceFile'] - def source_file - target_resource.source_file + def file_descriptor + target_resource.file_descriptor end Contract Maybe[String] diff --git a/middleman-core/lib/middleman-core/sitemap/resource.rb b/middleman-core/lib/middleman-core/sitemap/resource.rb index 56768900..14b43fd7 100644 --- a/middleman-core/lib/middleman-core/sitemap/resource.rb +++ b/middleman-core/lib/middleman-core/sitemap/resource.rb @@ -24,7 +24,7 @@ module Middleman # The on-disk source file for this resource, if there is one # @return [String] Contract Maybe[IsA['Middleman::SourceFile']] - attr_reader :source_file + attr_reader :file_descriptor # The path to use when requesting this resource. Normally it's # the same as {#destination_path} but it can be overridden in subclasses. @@ -41,21 +41,21 @@ module Middleman # Initialize resource with parent store and URL # @param [Middleman::Sitemap::Store] store # @param [String] path - # @param [String] source_file + # @param [String] source Contract IsA['Middleman::Sitemap::Store'], String, Maybe[Or[IsA['Middleman::SourceFile'], String]] => Any - def initialize(store, path, source_file=nil) + def initialize(store, path, source=nil) @store = store @app = @store.app @path = path - if source_file && source_file.is_a?(String) - source_file = Pathname(source_file) + if source && source.is_a?(String) + source = Pathname(source) end - if source_file && source_file.is_a?(Pathname) - @source_file = ::Middleman::SourceFile.new(source_file.relative_path_from(@app.source_dir), source_file, @app.source_dir, Set.new([:source])) + if source && source.is_a?(Pathname) + @file_descriptor = ::Middleman::SourceFile.new(source.relative_path_from(@app.source_dir), source, @app.source_dir, Set.new([:source])) else - @source_file = source_file + @file_descriptor = source end @destination_path = @path @@ -71,8 +71,15 @@ module Middleman # @return [Boolean] Contract Bool def template? - return false if source_file.nil? - !::Tilt[source_file[:full_path].to_s].nil? + return false if file_descriptor.nil? + !::Tilt[file_descriptor[:full_path].to_s].nil? + end + + # Backwards compatible method for turning descriptor into a string. + # @return [String] + Contract String + def source_file + file_descriptor && file_descriptor[:full_path].to_s end # Merge in new metadata specific to this resource. @@ -119,9 +126,9 @@ module Middleman # @return [String] Contract Hash, Hash => String def render(opts={}, locs={}) - return ::Middleman::FileRenderer.new(@app, source_file[:full_path].to_s).template_data_for_file unless template? + return ::Middleman::FileRenderer.new(@app, file_descriptor[:full_path].to_s).template_data_for_file unless template? - ::Middleman::Util.instrument 'render.resource', path: source_file[:full_path].to_s, destination_path: destination_path do + ::Middleman::Util.instrument 'render.resource', path: file_descriptor[:full_path].to_s, destination_path: destination_path do md = metadata opts = md[:options].deep_merge(opts) locs = md[:locals].deep_merge(locs) @@ -132,7 +139,7 @@ module Middleman opts[:layout] = false if %w(.js .json .css .txt).include?(ext) end - renderer = ::Middleman::TemplateRenderer.new(@app, source_file[:full_path].to_s) + renderer = ::Middleman::TemplateRenderer.new(@app, file_descriptor[:full_path].to_s) renderer.render(locs, opts) end end @@ -155,7 +162,7 @@ module Middleman # @return [Boolean] Contract Bool def binary? - !source_file.nil? && ::Middleman::Util.binary?(source_file[:full_path].to_s) + !file_descriptor.nil? && ::Middleman::Util.binary?(file_descriptor[:full_path].to_s) end # Ignore a resource directly, without going through the whole @@ -174,7 +181,7 @@ module Middleman # Ignore based on the source path (without template extensions) return true if @app.sitemap.ignored?(path) # This allows files to be ignored by their source file name (with template extensions) - if !self.is_a?(ProxyResource) && source_file && @app.sitemap.ignored?(source_file[:relative_path].to_s) + if !self.is_a?(ProxyResource) && file_descriptor && @app.sitemap.ignored?(file_descriptor[:relative_path].to_s) true else false diff --git a/middleman-core/lib/middleman-core/template_context.rb b/middleman-core/lib/middleman-core/template_context.rb index 368742b4..48498d85 100644 --- a/middleman-core/lib/middleman-core/template_context.rb +++ b/middleman-core/lib/middleman-core/template_context.rb @@ -128,7 +128,7 @@ module Middleman return unless resource = sitemap.find_resource_by_destination_path(current_path) # Look for partials relative to the current path - current_dir = resource.source_file[:relative_path].dirname + current_dir = resource.file_descriptor[:relative_path].dirname non_root = partial_path.to_s.sub(/^\//, '') relative_dir = current_dir + Pathname(non_root) @@ -138,7 +138,7 @@ module Middleman partial_file = nil [ - [relative_dir.to_s, { preferred_engine: resource.source_file[:relative_path].extname[1..-1].to_sym }], + [relative_dir.to_s, { preferred_engine: resource.file_descriptor[:relative_path].extname[1..-1].to_sym }], [non_root], [non_root, { try_static: try_static }], [relative_dir_no_underscore.to_s, { try_static: try_static }], From 40f023f01cb02e2972ac6732b70d518db68a1ae5 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sat, 12 Sep 2015 16:15:32 -0700 Subject: [PATCH 103/364] Let's do this --- middleman-core/lib/middleman-core/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleman-core/lib/middleman-core/version.rb b/middleman-core/lib/middleman-core/version.rb index a141218d..ebccc3f9 100644 --- a/middleman-core/lib/middleman-core/version.rb +++ b/middleman-core/lib/middleman-core/version.rb @@ -1,5 +1,5 @@ module Middleman # Current Version # @return [String] - VERSION = '4.0.0.beta.3' unless const_defined?(:VERSION) + VERSION = '4.0.0.rc.1' unless const_defined?(:VERSION) end From d99b922e671b50cad4b4b8078dd78a58b7602eba Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sat, 12 Sep 2015 16:16:26 -0700 Subject: [PATCH 104/364] Let's do this --- middleman/middleman.gemspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/middleman/middleman.gemspec b/middleman/middleman.gemspec index f1bffe12..c1fa5372 100644 --- a/middleman/middleman.gemspec +++ b/middleman/middleman.gemspec @@ -20,8 +20,8 @@ Gem::Specification.new do |s| s.add_dependency('middleman-core', Middleman::VERSION) s.add_dependency('middleman-cli', Middleman::VERSION) - s.add_dependency('middleman-sprockets', '>= 4.0.0.beta.1') - s.add_dependency('middleman-compass', '>= 4.0.0.beta.1.1') + s.add_dependency('middleman-sprockets', '>= 4.0.0.rc.1') + s.add_dependency('middleman-compass', '>= 4.0.0.rc.1') s.add_dependency('sass', ['>= 3.4.0', '< 4.0']) s.add_dependency('compass-import-once', ['1.0.5']) s.add_dependency('haml', ['>= 4.0.5']) From 8c02eb2a26801a9a5737d07c23158992dae7cb8c Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 14 Sep 2015 17:37:35 -0700 Subject: [PATCH 105/364] Some tweaks to get blog working --- .../core_extensions/front_matter.rb | 2 +- .../middleman-core/sitemap/extensions/ignores.rb | 2 ++ .../middleman-core/sitemap/extensions/on_disk.rb | 2 ++ .../middleman-core/sitemap/extensions/proxies.rb | 15 +++++++++++++++ .../sitemap/extensions/redirects.rb | 2 ++ .../sitemap/extensions/request_endpoints.rb | 2 ++ .../lib/middleman-core/sitemap/store.rb | 1 + 7 files changed, 25 insertions(+), 1 deletion(-) 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 03d2f431..d685e994 100644 --- a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb @@ -12,7 +12,7 @@ require 'middleman-core/util/data' module Middleman::CoreExtensions class FrontMatter < ::Middleman::Extension # Try to run after routing but before directory_indexes - self.resource_list_manipulator_priority = 90 + self.resource_list_manipulator_priority = 10 def initialize(app, options_hash={}, &block) super diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb index 9ba53899..0e54b2c2 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/ignores.rb @@ -3,6 +3,8 @@ module Middleman module Extensions # Class to handle managing ignores class Ignores < Extension + self.resource_list_manipulator_priority = 0 + # Expose `create_ignore` as `app.ignore` expose_to_application ignore: :create_ignore diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/on_disk.rb b/middleman-core/lib/middleman-core/sitemap/extensions/on_disk.rb index ba8f656e..a0d03400 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/on_disk.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/on_disk.rb @@ -5,6 +5,8 @@ module Middleman module Sitemap module Extensions class OnDisk < Extension + self.resource_list_manipulator_priority = 0 + def initialize(app, config={}, &block) super diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb index 78d6e17a..0285726f 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb @@ -7,6 +7,8 @@ module Middleman # Manages the list of proxy configurations and manipulates the sitemap # to include new resources based on those configurations class Proxies < Extension + self.resource_list_manipulator_priority = 0 + # Expose `create_proxy` as `app.proxy` expose_to_application proxy: :create_proxy @@ -83,7 +85,16 @@ module Middleman end end + class Resource + def proxy_to(path) + throw "Resource#proxy_to has been removed. Use ProxyResource class instead." + end + end + class ProxyResource < ::Middleman::Sitemap::Resource + Contract String + attr_reader :target + # Initialize resource with parent store and URL # @param [Middleman::Sitemap::Store] store # @param [String] path @@ -119,6 +130,10 @@ module Middleman target_resource.file_descriptor end + def metadata + target_resource.metadata.deep_merge super + end + Contract Maybe[String] def content_type mime_type = super diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/redirects.rb b/middleman-core/lib/middleman-core/sitemap/extensions/redirects.rb index e42d34dc..dc0c74f9 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/redirects.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/redirects.rb @@ -7,6 +7,8 @@ module Middleman # Manages the list of proxy configurations and manipulates the sitemap # to include new resources based on those configurations class Redirects < Extension + self.resource_list_manipulator_priority = 0 + # Expose `create_redirect` to config as `redirect` expose_to_config redirect: :create_redirect diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/request_endpoints.rb b/middleman-core/lib/middleman-core/sitemap/extensions/request_endpoints.rb index fc66cd71..245df873 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/request_endpoints.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/request_endpoints.rb @@ -4,6 +4,8 @@ module Middleman module Sitemap module Extensions class RequestEndpoints < Extension + self.resource_list_manipulator_priority = 0 + # Expose `create_endpoint` to config as `endpoint` expose_to_config endpoint: :create_endpoint diff --git a/middleman-core/lib/middleman-core/sitemap/store.rb b/middleman-core/lib/middleman-core/sitemap/store.rb index 129fa9b5..f7af3bd2 100644 --- a/middleman-core/lib/middleman-core/sitemap/store.rb +++ b/middleman-core/lib/middleman-core/sitemap/store.rb @@ -188,6 +188,7 @@ module Middleman @app.logger.debug '== Rebuilding resource list' @resources = @resource_list_manipulators.reduce([]) do |result, m| + @app.logger.debug "== Running manipulator: #{m[:name]}" newres = m[:manipulator].send(m[:custom_name] || :manipulate_resource_list, result) # Reset lookup cache From ed405b266f52cef8a7da0bc3697bc8e244aed003 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 14 Sep 2015 17:46:12 -0700 Subject: [PATCH 106/364] bump target ruby version --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 36463c2b..7c93ae0a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ rvm: - ruby-head - jruby-head - jruby-19mode - - 2.2 + - 2.2.2 - 2.1 - 2.0 os: From 260c6be66c1f039847a391d5011d96621ae9ec98 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 16 Sep 2015 10:53:31 -0700 Subject: [PATCH 107/364] Move compass and sprockets to template config --- middleman/middleman.gemspec | 2 -- 1 file changed, 2 deletions(-) diff --git a/middleman/middleman.gemspec b/middleman/middleman.gemspec index c1fa5372..33167d3d 100644 --- a/middleman/middleman.gemspec +++ b/middleman/middleman.gemspec @@ -20,8 +20,6 @@ Gem::Specification.new do |s| s.add_dependency('middleman-core', Middleman::VERSION) s.add_dependency('middleman-cli', Middleman::VERSION) - s.add_dependency('middleman-sprockets', '>= 4.0.0.rc.1') - s.add_dependency('middleman-compass', '>= 4.0.0.rc.1') s.add_dependency('sass', ['>= 3.4.0', '< 4.0']) s.add_dependency('compass-import-once', ['1.0.5']) s.add_dependency('haml', ['>= 4.0.5']) From 2b2ee10d81be2e51d2e0c0f04f5d89b4fd7a2612 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Wed, 16 Sep 2015 14:01:39 -0700 Subject: [PATCH 108/364] dont autoload stuff when bundler will load --- middleman/lib/middleman.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/middleman/lib/middleman.rb b/middleman/lib/middleman.rb index 01b9aa97..878b9c59 100644 --- a/middleman/lib/middleman.rb +++ b/middleman/lib/middleman.rb @@ -2,6 +2,3 @@ require 'middleman-core' # Make the VERSION string available require 'middleman-core/version' - -require 'middleman-sprockets' -require 'middleman-compass' From a251c82562efccb4819295b364e6445b1ab799da Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 20 Jul 2015 12:13:10 -0700 Subject: [PATCH 109/364] Add test for #1568 --- middleman-core/features/chained_templates.feature | 5 ++++- .../chained-app/source/test.html.combobreaker.str.erb | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 middleman-core/fixtures/chained-app/source/test.html.combobreaker.str.erb diff --git a/middleman-core/features/chained_templates.feature b/middleman-core/features/chained_templates.feature index 7f538b65..4647e7eb 100644 --- a/middleman-core/features/chained_templates.feature +++ b/middleman-core/features/chained_templates.feature @@ -13,10 +13,13 @@ Feature: Templates should be chainable When I cd to "build" Then the following files should exist: | index.html | - + | test.html.combobreaker | And the file "index.html" should contain "Title" And the file "index.html" should contain "Subtitle" And the file "index.html" should contain "Sup" + And the file "test.html.combobreaker.html" should contain "Title" + And the file "test.html.combobreaker.html" should contain "Subtitle" + And the file "test.html.combobreaker.html" should contain "Sup" Scenario: Partials are parsed by multiple template engines: Outer template has .erb and inner .md.erb Given a fixture app "partial-chained_templates-app" diff --git a/middleman-core/fixtures/chained-app/source/test.html.combobreaker.str.erb b/middleman-core/fixtures/chained-app/source/test.html.combobreaker.str.erb new file mode 100644 index 00000000..3b7caec2 --- /dev/null +++ b/middleman-core/fixtures/chained-app/source/test.html.combobreaker.str.erb @@ -0,0 +1,8 @@ +--- +layout: false +sup: "Sup" +--- + +

    #{"<%= data.article.title %>"}

    +

    #{"<%= data.article.subtitle %>"}

    +

    #{"<%= current_page.data.sup %>"}

    From 409a892da707aab0eef848ae79fc7ad97700199d Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Thu, 17 Sep 2015 09:41:17 -0700 Subject: [PATCH 110/364] Forward port some stable changes --- .editorconfig | 13 +++++++++++++ .rubocop.yml | 2 -- .../middleman-cli/templates/extension/Rakefile | 2 +- middleman-core/.rspec | 1 + middleman-core/cucumber.yml | 2 ++ .../features/chained_templates.feature | 16 ++++++++-------- ...ker.str.erb => test.erb.combobreaker.str.erb} | 0 middleman-core/lib/middleman-core/application.rb | 2 -- .../core_extensions/default_helpers.rb | 3 ++- .../lib/middleman-core/extensions/asset_hash.rb | 2 +- .../lib/middleman-core/preview_server.rb | 4 ++-- middleman-core/lib/middleman-core/rack.rb | 2 +- .../lib/middleman-core/renderers/haml.rb | 3 +-- .../middleman-core/sitemap/extensions/proxies.rb | 4 ++-- .../lib/middleman-core/sitemap/resource.rb | 4 +--- .../lib/middleman-core/sitemap/store.rb | 13 +++++++------ .../lib/middleman-core/sources/source_watcher.rb | 6 ++---- .../lib/middleman-core/template_context.rb | 3 ++- middleman-core/lib/middleman-core/util/data.rb | 6 +++--- 19 files changed, 49 insertions(+), 39 deletions(-) create mode 100644 .editorconfig create mode 100644 middleman-core/.rspec create mode 100644 middleman-core/cucumber.yml rename middleman-core/fixtures/chained-app/source/{test.html.combobreaker.str.erb => test.erb.combobreaker.str.erb} (100%) diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..5d126348 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.rubocop.yml b/.rubocop.yml index 652f08fb..337be055 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -25,8 +25,6 @@ ClassLength: Enabled: false Documentation: Enabled: false -Encoding: - Enabled: false HashSyntax: EnforcedStyle: ruby19 SpaceAroundEqualsInParameterDefault: diff --git a/middleman-cli/lib/middleman-cli/templates/extension/Rakefile b/middleman-cli/lib/middleman-cli/templates/extension/Rakefile index 529dfacf..4c62996f 100644 --- a/middleman-cli/lib/middleman-cli/templates/extension/Rakefile +++ b/middleman-cli/lib/middleman-cli/templates/extension/Rakefile @@ -4,7 +4,7 @@ Bundler::GemHelper.install_tasks require 'cucumber/rake/task' Cucumber::Rake::Task.new(:cucumber, 'Run features that should pass') do |t| - t.cucumber_opts = "--color --tags ~@wip --strict" + t.cucumber_opts = '--color --tags ~@wip --strict' end require 'rake/clean' diff --git a/middleman-core/.rspec b/middleman-core/.rspec new file mode 100644 index 00000000..5052887a --- /dev/null +++ b/middleman-core/.rspec @@ -0,0 +1 @@ +--color \ No newline at end of file diff --git a/middleman-core/cucumber.yml b/middleman-core/cucumber.yml new file mode 100644 index 00000000..922a378c --- /dev/null +++ b/middleman-core/cucumber.yml @@ -0,0 +1,2 @@ +default: --require features --tags ~@wip +wip: --require features --tags @wip \ No newline at end of file diff --git a/middleman-core/features/chained_templates.feature b/middleman-core/features/chained_templates.feature index 4647e7eb..27135bf6 100644 --- a/middleman-core/features/chained_templates.feature +++ b/middleman-core/features/chained_templates.feature @@ -7,19 +7,19 @@ Feature: Templates should be chainable Then I should see "Title" And I should see "Subtitle" And I should see "Sup" - + Scenario: Build chained template Given a successfully built app at "chained-app" When I cd to "build" Then the following files should exist: | index.html | - | test.html.combobreaker | + | test.erb.combobreaker | And the file "index.html" should contain "Title" And the file "index.html" should contain "Subtitle" And the file "index.html" should contain "Sup" - And the file "test.html.combobreaker.html" should contain "Title" - And the file "test.html.combobreaker.html" should contain "Subtitle" - And the file "test.html.combobreaker.html" should contain "Sup" + And the file "test.erb.combobreaker" should contain "Title" + And the file "test.erb.combobreaker" should contain "Subtitle" + And the file "test.erb.combobreaker" should contain "Sup" Scenario: Partials are parsed by multiple template engines: Outer template has .erb and inner .md.erb Given a fixture app "partial-chained_templates-app" @@ -32,7 +32,7 @@ Feature: Templates should be chainable And a template named "my_partial.html.md.erb" with: """ ## My Partial - + <%= 'hello world' %> """ And the Server is running @@ -61,7 +61,7 @@ Feature: Templates should be chainable And a template named "my_partial.html.md.erb" with: """ ## My Partial - + <%= 'hello world' %> """ And the Server is running @@ -90,7 +90,7 @@ Feature: Templates should be chainable And a template named "my_partial.html.erb" with: """

    My Partial

    - + <%= 'hello world' %> """ And the Server is running diff --git a/middleman-core/fixtures/chained-app/source/test.html.combobreaker.str.erb b/middleman-core/fixtures/chained-app/source/test.erb.combobreaker.str.erb similarity index 100% rename from middleman-core/fixtures/chained-app/source/test.html.combobreaker.str.erb rename to middleman-core/fixtures/chained-app/source/test.erb.combobreaker.str.erb diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index 9ee3f4b9..6c39af54 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -1,5 +1,3 @@ -# Use ActiveSupport JSON -require 'active_support/json' require 'active_support/core_ext/integer/inflections' require 'middleman-core/contracts' diff --git a/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb b/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb index 71666bab..ba508c4d 100644 --- a/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb +++ b/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb @@ -7,7 +7,8 @@ require 'padrino-helpers' class Padrino::Helpers::OutputHelpers::ErbHandler # Force Erb capture not to use safebuffer def capture_from_template(*args, &block) - self.output_buffer, buf_was = '', output_buffer + self.output_buffer = '' + buf_was = output_buffer raw = block.call(*args) captured = template.instance_variable_get(:@_out_buf) self.output_buffer = buf_was diff --git a/middleman-core/lib/middleman-core/extensions/asset_hash.rb b/middleman-core/lib/middleman-core/extensions/asset_hash.rb index e3248bd5..bb1389e9 100644 --- a/middleman-core/lib/middleman-core/extensions/asset_hash.rb +++ b/middleman-core/lib/middleman-core/extensions/asset_hash.rb @@ -17,7 +17,7 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension def after_configuration # Allow specifying regexes to ignore, plus always ignore apple touch icons @ignore = Array(options.ignore) + [/^apple-touch-icon/] - + app.use ::Middleman::Middleware::InlineURLRewriter, id: :asset_hash, url_extensions: options.exts, diff --git a/middleman-core/lib/middleman-core/preview_server.rb b/middleman-core/lib/middleman-core/preview_server.rb index 4d727bd1..d9f5c172 100644 --- a/middleman-core/lib/middleman-core/preview_server.rb +++ b/middleman-core/lib/middleman-core/preview_server.rb @@ -125,8 +125,8 @@ module Middleman # config.rb watcher = files.watch :reload, - path: root, - only: match_against + path: root, + only: match_against # Hack around node_modules in root. watcher.listener.ignore(/^node_modules/) diff --git a/middleman-core/lib/middleman-core/rack.rb b/middleman-core/lib/middleman-core/rack.rb index a6743c59..3e2a6f25 100644 --- a/middleman-core/lib/middleman-core/rack.rb +++ b/middleman-core/lib/middleman-core/rack.rb @@ -102,7 +102,7 @@ module Middleman begin # Write out the contents of the page - res.write resource.render({}, { rack: { request: req } }) + res.write resource.render({}, rack: { request: req }) # Valid content is a 200 status res.status = 200 diff --git a/middleman-core/lib/middleman-core/renderers/haml.rb b/middleman-core/lib/middleman-core/renderers/haml.rb index 7e2b6fbb..24cdced4 100644 --- a/middleman-core/lib/middleman-core/renderers/haml.rb +++ b/middleman-core/lib/middleman-core/renderers/haml.rb @@ -40,7 +40,6 @@ module Middleman # Haml Renderer class Haml < ::Middleman::Extension - def initialize(app, options={}, &block) super @@ -53,7 +52,7 @@ module Middleman modified_options = options.dup modified_options[:context] = compiler_options[:context] - text = template_class.new(nil, 1, modified_options) {text}.render + text = template_class.new(nil, 1, modified_options) { text }.render super(text, compiler_options) 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 0285726f..110d9890 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb @@ -86,8 +86,8 @@ module Middleman end class Resource - def proxy_to(path) - throw "Resource#proxy_to has been removed. Use ProxyResource class instead." + def proxy_to(_path) + throw 'Resource#proxy_to has been removed. Use ProxyResource class instead.' end end diff --git a/middleman-core/lib/middleman-core/sitemap/resource.rb b/middleman-core/lib/middleman-core/sitemap/resource.rb index 14b43fd7..4a247cb8 100644 --- a/middleman-core/lib/middleman-core/sitemap/resource.rb +++ b/middleman-core/lib/middleman-core/sitemap/resource.rb @@ -48,9 +48,7 @@ module Middleman @app = @store.app @path = path - if source && source.is_a?(String) - source = Pathname(source) - end + source = Pathname(source) if source && source.is_a?(String) if source && source.is_a?(Pathname) @file_descriptor = ::Middleman::SourceFile.new(source.relative_path_from(@app.source_dir), source, @app.source_dir, Set.new([:source])) diff --git a/middleman-core/lib/middleman-core/sitemap/store.rb b/middleman-core/lib/middleman-core/sitemap/store.rb index f7af3bd2..54e6b1ce 100644 --- a/middleman-core/lib/middleman-core/sitemap/store.rb +++ b/middleman-core/lib/middleman-core/sitemap/store.rb @@ -187,23 +187,24 @@ module Middleman @app.logger.debug '== Rebuilding resource list' - @resources = @resource_list_manipulators.reduce([]) do |result, m| + @resources = [] + + @resource_list_manipulators.each do |m| @app.logger.debug "== Running manipulator: #{m[:name]}" - newres = m[:manipulator].send(m[:custom_name] || :manipulate_resource_list, result) + @resources = m[:manipulator].send(m[:custom_name] || :manipulate_resource_list, @resources) # Reset lookup cache reset_lookup_cache! # Rebuild cache - newres.each do |resource| + @resources.each do |resource| @_lookup_by_path[resource.path] = resource @_lookup_by_destination_path[resource.destination_path] = resource end - newres + invalidate_resources_not_ignored_cache! end - invalidate_resources_not_ignored_cache! @update_count += 1 end end @@ -223,7 +224,7 @@ module Middleman Contract String => String def remove_templating_extensions(path) # Strip templating extensions as long as Tilt knows them - path = path.sub(File.extname(path), '') while ::Tilt[path] + path = path.sub(/#{::Regexp.escape(File.extname(path))}$/, '') while ::Tilt[path] path end diff --git a/middleman-core/lib/middleman-core/sources/source_watcher.rb b/middleman-core/lib/middleman-core/sources/source_watcher.rb index 82dc8f74..38ac639a 100644 --- a/middleman-core/lib/middleman-core/sources/source_watcher.rb +++ b/middleman-core/lib/middleman-core/sources/source_watcher.rb @@ -8,16 +8,14 @@ require 'backports/2.0.0/enumerable/lazy' module Listen class Silencer # TODO: switch type and path places - and verify - def silenced?(relative_path, type) + def silenced?(relative_path, _type) path = relative_path.to_s # if only_patterns && type == :file # return true unless only_patterns.any? { |pattern| path =~ pattern } # end - if only_patterns - return !only_patterns.any? { |pattern| path =~ pattern } - end + return !only_patterns.any? { |pattern| path =~ pattern } if only_patterns ignore_patterns.any? { |pattern| path =~ pattern } end diff --git a/middleman-core/lib/middleman-core/template_context.rb b/middleman-core/lib/middleman-core/template_context.rb index 48498d85..6771ddbe 100644 --- a/middleman-core/lib/middleman-core/template_context.rb +++ b/middleman-core/lib/middleman-core/template_context.rb @@ -71,7 +71,8 @@ module Middleman engine = extension[1..-1].to_sym # Store last engine for later (could be inside nested renders) - self.current_engine, engine_was = engine, current_engine + self.current_engine = engine + engine_was = current_engine # By default, no content is captured content = '' diff --git a/middleman-core/lib/middleman-core/util/data.rb b/middleman-core/lib/middleman-core/util/data.rb index a02d64e2..781ed5c0 100644 --- a/middleman-core/lib/middleman-core/util/data.rb +++ b/middleman-core/lib/middleman-core/util/data.rb @@ -11,11 +11,11 @@ require 'middleman-core/util' require 'yaml' # Parsing JSON data -require 'active_support/json' +require 'json' module Middleman module Util - module Data + module Data include Contracts module_function @@ -121,7 +121,7 @@ module Middleman Contract String, Pathname => Maybe[[Hash, String]] def parse_json(content, full_path) begin - data = map_value(::ActiveSupport::JSON.decode(content)) + data = map_value(::JSON.parse(content)) rescue => e $stderr.puts "JSON Exception parsing #{full_path}: #{e.message}" return nil From 2907761556ae7e84e28c26bdcb73b1037225db8e Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Thu, 17 Sep 2015 14:46:27 -0700 Subject: [PATCH 111/364] tweak logger ref --- .../lib/middleman-core/preview_server.rb | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/middleman-core/lib/middleman-core/preview_server.rb b/middleman-core/lib/middleman-core/preview_server.rb index a32262fd..40275df5 100644 --- a/middleman-core/lib/middleman-core/preview_server.rb +++ b/middleman-core/lib/middleman-core/preview_server.rb @@ -14,7 +14,6 @@ module Middleman extend Forwardable attr_reader :app, :ssl_certificate, :ssl_private_key, :environment, :server_information - def_delegator :app, :logger def https? @https == true @@ -43,11 +42,11 @@ module Middleman mount_instance(the_app) - logger.debug %(== Server information is provided by #{server_information.handler}) - logger.debug %(== The Middleman is running in "#{environment}" environment) - logger.debug format('== The Middleman preview server is bound to %s', ServerUrl.new(hosts: server_information.listeners, port: server_information.port, https: https?).to_bind_addresses.join(', ')) - logger.info format('== View your site at %s', ServerUrl.new(hosts: server_information.site_addresses, port: server_information.port, https: https?).to_urls.join(', ')) - logger.info format('== Inspect your site configuration at %s', ServerUrl.new(hosts: server_information.site_addresses, port: server_information.port, https: https?).to_config_urls.join(', ')) + app.logger.debug %(== Server information is provided by #{server_information.handler}) + app.logger.debug %(== The Middleman is running in "#{environment}" environment) + app.logger.debug format('== The Middleman preview server is bound to %s', ServerUrl.new(hosts: server_information.listeners, port: server_information.port, https: https?).to_bind_addresses.join(', ')) + app.logger.info format('== View your site at %s', ServerUrl.new(hosts: server_information.site_addresses, port: server_information.port, https: https?).to_urls.join(', ')) + app.logger.info format('== Inspect your site configuration at %s', ServerUrl.new(hosts: server_information.site_addresses, port: server_information.port, https: https?).to_config_urls.join(', ')) @initialized ||= false return if @initialized @@ -77,7 +76,7 @@ module Middleman # @return [void] def stop begin - logger.info '== The Middleman is shutting down' + app.logger.info '== The Middleman is shutting down' rescue # if the user closed their terminal STDOUT/STDERR won't exist end @@ -88,13 +87,13 @@ module Middleman # Simply stop, then start the server # @return [void] def reload - logger.info '== The Middleman is reloading' + app.logger.info '== The Middleman is reloading' begin app = initialize_new_app rescue => e - logger.error "Error reloading Middleman: #{e}\n#{e.backtrace.join("\n")}" - logger.info '== The Middleman is still running the application from before the error' + $stderr.puts "Error reloading Middleman: #{e}\n#{e.backtrace.join("\n")}" + app.logger.info '== The Middleman is still running the application from before the error' return end @@ -105,7 +104,7 @@ module Middleman mount_instance(app) - logger.info '== The Middleman has reloaded' + app.logger.info '== The Middleman has reloaded' end # Stop the current instance, exit Webrick @@ -143,7 +142,7 @@ module Middleman %r{^config\.rb$}, %r{^environments/[^\.](.*)\.rb$}, %r{^lib/[^\.](.*)\.rb$}, - %r{^#{@app.config[:helpers_dir]}/[^\.](.*)\.rb$} + %r{^#{config[:helpers_dir]}/[^\.](.*)\.rb$} ] # config.rb @@ -169,7 +168,7 @@ module Middleman # `server_information` server_information.use app.config - logger.warn format('== The Middleman uses a different port "%s" then the configured one "%s" because some other server is listening on that port.', server_information.port, configured_port) unless app.config[:port] == configured_port + app.logger.warn format('== The Middleman uses a different port "%s" then the configured one "%s" because some other server is listening on that port.', server_information.port, configured_port) unless app.config[:port] == configured_port @https = app.config[:https] @environment = app.config[:environment] @@ -245,7 +244,7 @@ module Middleman begin ::WEBrick::HTTPServer.new(http_opts) rescue Errno::EADDRINUSE - logger.error %(== Port "#{http_opts[:Port]}" is in use. This should not have happened. Please start "middleman server" again.) + $stderr.puts %(== Port "#{http_opts[:Port]}" is in use. This should not have happened. Please start "middleman server" again.) end end From 3ae28874bf3fe82368a41386ce768b553fe24f59 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sat, 19 Sep 2015 14:07:42 -0700 Subject: [PATCH 112/364] Fix test breakage --- .../lib/middleman-core/application.rb | 3 +- .../core_extensions/front_matter.rb | 2 +- .../middleman-core/core_extensions/routing.rb | 2 +- .../extensions/automatic_image_sizes.rb | 3 +- .../extensions/minify_javascript.rb | 2 +- middleman-core/lib/middleman-core/rack.rb | 6 ++ .../step_definitions/middleman_steps.rb | 8 +-- .../step_definitions/server_steps.rb | 56 +++++++++---------- 8 files changed, 45 insertions(+), 37 deletions(-) diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index f8cb7563..0712eed1 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -334,8 +334,9 @@ module Middleman end # Whether we're in a specific environment + # @param [Symbol] key # @return [Boolean] - Contract Bool + Contract Symbol => Bool def environment?(key) config[:environment] == key end diff --git a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb index d685e994..a133d0ef 100644 --- a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb +++ b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb @@ -12,7 +12,7 @@ require 'middleman-core/util/data' module Middleman::CoreExtensions class FrontMatter < ::Middleman::Extension # Try to run after routing but before directory_indexes - self.resource_list_manipulator_priority = 10 + self.resource_list_manipulator_priority = 20 def initialize(app, options_hash={}, &block) super diff --git a/middleman-core/lib/middleman-core/core_extensions/routing.rb b/middleman-core/lib/middleman-core/core_extensions/routing.rb index 0601d2d0..3e66f3dc 100644 --- a/middleman-core/lib/middleman-core/core_extensions/routing.rb +++ b/middleman-core/lib/middleman-core/core_extensions/routing.rb @@ -4,7 +4,7 @@ module Middleman class Routing < Extension # This should always run late, but not as late as :directory_indexes, # so it can add metadata to any pages generated by other extensions - self.resource_list_manipulator_priority = 80 + self.resource_list_manipulator_priority = 10 # Expose the `page` method to config. expose_to_config :page diff --git a/middleman-core/lib/middleman-core/extensions/automatic_image_sizes.rb b/middleman-core/lib/middleman-core/extensions/automatic_image_sizes.rb index aa184df9..b88721de 100644 --- a/middleman-core/lib/middleman-core/extensions/automatic_image_sizes.rb +++ b/middleman-core/lib/middleman-core/extensions/automatic_image_sizes.rb @@ -23,7 +23,8 @@ class Middleman::Extensions::AutomaticImageSizes < ::Middleman::Extension if file && file[:full_path].exist? begin - width, height = ::FastImage.size(file[:full_path].to_s, raise_on_failure: true) + full_path = file[:full_path].to_s + width, height = ::FastImage.size(full_path, raise_on_failure: true) # Check for @2x and @3x image retina = full_path.match(/@(\d)x\.[a-zA-Z]{3,4}$/) if retina diff --git a/middleman-core/lib/middleman-core/extensions/minify_javascript.rb b/middleman-core/lib/middleman-core/extensions/minify_javascript.rb index 4ab0979a..73a75cd0 100644 --- a/middleman-core/lib/middleman-core/extensions/minify_javascript.rb +++ b/middleman-core/lib/middleman-core/extensions/minify_javascript.rb @@ -13,7 +13,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension def ready # Setup Rack middleware to minify JS - app.use Rack, compressor: chosen_compressor, + app.use Rack, compressor: options[:compressor], ignore: Array(options[:ignore]) + [/\.min\./], inline: options[:inline], content_types: options[:content_types], diff --git a/middleman-core/lib/middleman-core/rack.rb b/middleman-core/lib/middleman-core/rack.rb index 3e2a6f25..4578005b 100644 --- a/middleman-core/lib/middleman-core/rack.rb +++ b/middleman-core/lib/middleman-core/rack.rb @@ -14,6 +14,12 @@ require 'middleman-core/template_renderer' ::Rack::Mime::MIME_TYPES['.html'] = 'text/html; charset=utf-8' ::Rack::Mime::MIME_TYPES['.htm'] = 'text/html; charset=utf-8' +# Sourcemap format +::Rack::Mime::MIME_TYPES['.map'] = 'application/json; charset=utf-8' + +# Create a MIME type for PHP files (for detection by extensions) +::Rack::Mime::MIME_TYPES['.php'] = 'text/php' + module Middleman class Rack extend Forwardable diff --git a/middleman-core/lib/middleman-core/step_definitions/middleman_steps.rb b/middleman-core/lib/middleman-core/step_definitions/middleman_steps.rb index 395ff3de..ff256a94 100644 --- a/middleman-core/lib/middleman-core/step_definitions/middleman_steps.rb +++ b/middleman-core/lib/middleman-core/step_definitions/middleman_steps.rb @@ -1,15 +1,15 @@ Then /^the file "([^\"]*)" has the contents$/ do |path, contents| write_file(path, contents) - cd(".") do + # cd(".") do @server_inst.files.find_new_files! - end + # end end Then /^the file "([^\"]*)" is removed$/ do |path| step %Q{I remove the file "#{path}"} - cd(".") do + # cd(".") do @server_inst.files.find_new_files! - end + # end end diff --git a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb index 448af3cf..1a80a118 100644 --- a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb +++ b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb @@ -1,3 +1,4 @@ +require 'middleman-core/rack' require 'rspec/expectations' require 'capybara/cucumber' @@ -41,7 +42,7 @@ Given /^the Server is running$/ do initialize_commands = @initialize_commands || [] - cd(".") do + # cd(".") do @server_inst = ::Middleman::Application.new do config[:watcher_disable] = true config[:show_exceptions] = false @@ -51,9 +52,8 @@ Given /^the Server is running$/ do end end - rack = ::Middleman::Rack.new(@server_inst) - Capybara.app = rack.to_app - end + Capybara.app = ::Middleman::Rack.new(@server_inst).to_app + # end end Given /^the Server is running at "([^\"]*)"$/ do |app_path| @@ -66,73 +66,73 @@ Given /^a template named "([^\"]*)" with:$/ do |name, string| end When /^I go to "([^\"]*)"$/ do |url| - cd(".") do + # cd(".") do visit(URI.encode(url).to_s) - end + # end end Then /^going to "([^\"]*)" should not raise an exception$/ do |url| - cd(".") do + # cd(".") do expect{ visit(URI.encode(url).to_s) }.to_not raise_exception - end + # end end Then /^the content type should be "([^\"]*)"$/ do |expected| - cd(".") do + # cd(".") do expect(page.response_headers['Content-Type']).to start_with expected - end + # end end Then /^I should see "([^\"]*)"$/ do |expected| - cd(".") do + # cd(".") do expect(page.body).to include expected - end + # end end Then /^I should see '([^\']*)'$/ do |expected| - cd(".") do + # cd(".") do expect(page.body).to include expected - end + # end end Then /^I should see:$/ do |expected| - cd(".") do + # cd(".") do expect(page.body).to include expected - end + # end end Then /^I should not see "([^\"]*)"$/ do |expected| - cd(".") do + # cd(".") do expect(page.body).not_to include expected - end + # end end Then /^I should see content matching %r{(.*)}$/ do |expected| - cd(".") do + # cd(".") do expect(page.body).to match(expected) - end + # end end Then /^I should not see content matching %r{(.*)}$/ do |expected| - cd(".") do + # cd(".") do expect(page.body).to_not match(expected) - end + # end end Then /^I should not see:$/ do |expected| - cd(".") do + # cd(".") do expect(page.body).not_to include expected - end + # end end Then /^the status code should be "([^\"]*)"$/ do |expected| - cd(".") do + # cd(".") do expect(page.status_code).to eq expected.to_i - end + # end end Then /^I should see "([^\"]*)" lines$/ do |lines| - cd(".") do + # cd(".") do expect(page.body.chomp.split($/).length).to eq lines.to_i - end + # end end From 3e1fc0aa1f83ba29b1eb89fb9463dc8d1c7a6987 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sat, 19 Sep 2015 14:26:30 -0700 Subject: [PATCH 113/364] Change test to respect global relative assets change --- CHANGELOG.md | 4 ++++ middleman-core/features/relative_assets.feature | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ae9a891..7c1b6569 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ master === +* `relative_assets` extension overrides local `relative: false` option to stylesheet/javascript tag helpers. + +# 4.0.0.rc.1 + * Removed ability to use JSON as frontmatter. Still allowed in data/ folder. * Added YAML data postscript. Like frontmatter, but reversed. Attach content after the key/value data as a `:postscript` key to the data structure (if Hash). diff --git a/middleman-core/features/relative_assets.feature b/middleman-core/features/relative_assets.feature index ac4d1776..e78f7665 100644 --- a/middleman-core/features/relative_assets.feature +++ b/middleman-core/features/relative_assets.feature @@ -59,15 +59,15 @@ Feature: Relative Assets When I cd to "build" Then the file "relative_image/index.html" should contain "../stylesheets/relative_assets.css" - Scenario: Rendering html with the feature enabled + Scenario: Rendering html with the feature enabled (overrides relative option on helpers) Given "relative_assets" feature is "enabled" And the Server is running at "relative-assets-app" When I go to "/relative_image.html" Then I should see '"stylesheets/relative_assets.css"' Then I should see '"javascripts/app.js"' When I go to "/relative_image_absolute_css.html" - Then I should see '"/stylesheets/relative_assets.css"' - Then I should see '"/javascripts/app.js"' + Then I should see '"stylesheets/relative_assets.css"' + Then I should see '"javascripts/app.js"' Then I should not see "/images/blank.gif" And I should see "images/blank.gif" @@ -121,4 +121,4 @@ Feature: Relative Assets """ And the Server is running at "relative-assets-app" When I go to "/sub/image_tag.html" - Then I should see '' \ No newline at end of file + Then I should see '' From 765de5ab11f682a919e9cdf0542571826d4946a9 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Sat, 19 Sep 2015 14:39:55 -0700 Subject: [PATCH 114/364] Remove ancient twitter bootstrap test. Use npm or bower, y'all --- Gemfile | 1 - .../twitter-bootstrap-compile.feature | 6 - .../fixtures/twitter-bootstrap-app/config.rb | 0 .../twitter-bootstrap-ebc6935/.gitignore | 36 - .../twitter-bootstrap-ebc6935/.travis.yml | 3 - .../source/twitter-bootstrap-ebc6935/LICENSE | 176 - .../twitter-bootstrap-ebc6935/README.md | 137 - .../img/glyphicons-halflings-white.png | Bin 8777 -> 0 bytes .../img/glyphicons-halflings.png | Bin 13826 -> 0 bytes .../twitter-bootstrap-ebc6935/js/.jshintrc | 10 - .../twitter-bootstrap-ebc6935/js/README.md | 112 - .../js/bootstrap-alert.js | 90 - .../js/bootstrap-button.js | 96 - .../js/bootstrap-carousel.js | 169 - .../js/bootstrap-collapse.js | 157 - .../js/bootstrap-dropdown.js | 100 - .../js/bootstrap-modal.js | 218 - .../js/bootstrap-popover.js | 98 - .../js/bootstrap-scrollspy.js | 151 - .../js/bootstrap-tab.js | 135 - .../js/bootstrap-tooltip.js | 275 - .../js/bootstrap-transition.js | 61 - .../js/bootstrap-typeahead.js | 285 - .../js/tests/index.html | 54 - .../js/tests/phantom.js | 63 - .../js/tests/server.js | 14 - .../js/tests/unit/bootstrap-alert.js | 56 - .../js/tests/unit/bootstrap-button.js | 77 - .../js/tests/unit/bootstrap-carousel.js | 28 - .../js/tests/unit/bootstrap-collapse.js | 54 - .../js/tests/unit/bootstrap-dropdown.js | 87 - .../js/tests/unit/bootstrap-modal.js | 114 - .../js/tests/unit/bootstrap-phantom.js | 21 - .../js/tests/unit/bootstrap-popover.js | 93 - .../js/tests/unit/bootstrap-scrollspy.js | 31 - .../js/tests/unit/bootstrap-tab.js | 61 - .../js/tests/unit/bootstrap-tooltip.js | 155 - .../js/tests/unit/bootstrap-transition.js | 13 - .../js/tests/unit/bootstrap-typeahead.js | 148 - .../js/tests/vendor/jquery.js | 9252 ----------------- .../js/tests/vendor/qunit.css | 232 - .../js/tests/vendor/qunit.js | 1510 --- .../less/_accordion.less | 33 - .../less/_alerts.less | 58 - .../less/_breadcrumbs.less | 24 - .../less/_button-groups.less | 191 - .../less/_buttons.less | 191 - .../less/_carousel.less | 121 - .../less/_close.less | 29 - .../twitter-bootstrap-ebc6935/less/_code.less | 57 - .../less/_component-animations.less | 20 - .../less/_dropdowns.less | 143 - .../less/_forms.less | 583 -- .../twitter-bootstrap-ebc6935/less/_grid.less | 5 - .../less/_hero-unit.less | 22 - .../less/_labels-badges.less | 55 - .../less/_layouts.less | 17 - .../less/_mixins.less | 646 -- .../less/_modals.less | 90 - .../less/_navbar.less | 358 - .../twitter-bootstrap-ebc6935/less/_navs.less | 363 - .../less/_pager.less | 36 - .../less/_pagination.less | 56 - .../less/_popovers.less | 49 - .../less/_progress-bars.less | 117 - .../less/_reset.less | 131 - .../less/_responsive-1200px-min.less | 26 - .../less/_responsive-767px-max.less | 149 - .../less/_responsive-768px-979px.less | 17 - .../less/_responsive-navbar.less | 153 - .../less/_responsive-utilities.less | 41 - .../less/_scaffolding.less | 29 - .../less/_sprites.less | 191 - .../less/_tables.less | 176 - .../less/_thumbnails.less | 47 - .../less/_tooltip.less | 35 - .../twitter-bootstrap-ebc6935/less/_type.less | 232 - .../less/_utilities.less | 23 - .../less/_variables.less | 206 - .../less/_wells.less | 27 - .../less/bootstrap.less | 62 - .../less/responsive.less | 48 - .../less/tests/css-tests.css | 52 - .../less/tests/css-tests.html | 917 -- .../less/tests/forms.html | 179 - .../less/tests/navbar.html | 108 - .../twitter-bootstrap-ebc6935/package.json | 25 - 87 files changed, 20517 deletions(-) delete mode 100644 middleman-core/features/twitter-bootstrap-compile.feature delete mode 100644 middleman-core/fixtures/twitter-bootstrap-app/config.rb delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/.gitignore delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/.travis.yml delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/LICENSE delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/README.md delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/img/glyphicons-halflings-white.png delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/img/glyphicons-halflings.png delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/.jshintrc delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/README.md delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-alert.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-button.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-carousel.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-collapse.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-dropdown.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-modal.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-popover.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-scrollspy.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-tab.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-tooltip.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-transition.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-typeahead.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/index.html delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/phantom.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/server.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/unit/bootstrap-alert.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/unit/bootstrap-button.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/unit/bootstrap-carousel.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/unit/bootstrap-collapse.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/unit/bootstrap-dropdown.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/unit/bootstrap-modal.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/unit/bootstrap-phantom.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/unit/bootstrap-popover.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/unit/bootstrap-scrollspy.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/unit/bootstrap-tab.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/unit/bootstrap-tooltip.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/unit/bootstrap-transition.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/unit/bootstrap-typeahead.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/vendor/jquery.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/vendor/qunit.css delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/tests/vendor/qunit.js delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_accordion.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_alerts.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_breadcrumbs.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_button-groups.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_buttons.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_carousel.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_close.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_code.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_component-animations.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_dropdowns.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_forms.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_grid.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_hero-unit.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_labels-badges.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_layouts.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_mixins.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_modals.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_navbar.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_navs.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_pager.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_pagination.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_popovers.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_progress-bars.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_reset.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_responsive-1200px-min.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_responsive-767px-max.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_responsive-768px-979px.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_responsive-navbar.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_responsive-utilities.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_scaffolding.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_sprites.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_tables.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_thumbnails.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_tooltip.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_type.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_utilities.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_variables.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/_wells.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/bootstrap.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/responsive.less delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/tests/css-tests.css delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/tests/css-tests.html delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/tests/forms.html delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/less/tests/navbar.html delete mode 100755 middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/package.json diff --git a/Gemfile b/Gemfile index 311f5476..3da827cc 100644 --- a/Gemfile +++ b/Gemfile @@ -15,7 +15,6 @@ gem 'cucumber', '~> 2.0', require: false gem 'haml', '>= 4.0.5', require: false gem 'coffee-script', '~> 2.2', require: false gem 'kramdown', '~> 1.2', require: false -gem 'less', '2.3', require: false gem 'slim', '>= 2.0', require: false gem 'liquid', '>= 2.6', require: false gem 'stylus', '>= 1.0', require: false diff --git a/middleman-core/features/twitter-bootstrap-compile.feature b/middleman-core/features/twitter-bootstrap-compile.feature deleted file mode 100644 index 2d7d0cdd..00000000 --- a/middleman-core/features/twitter-bootstrap-compile.feature +++ /dev/null @@ -1,6 +0,0 @@ -@nowindows -Feature: Compile a complicated Twitter bootstrap app - - Scenario: User drops Twitter Bootstrap source into an app - - Given a successfully built app at "twitter-bootstrap-app" diff --git a/middleman-core/fixtures/twitter-bootstrap-app/config.rb b/middleman-core/fixtures/twitter-bootstrap-app/config.rb deleted file mode 100644 index e69de29b..00000000 diff --git a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/.gitignore b/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/.gitignore deleted file mode 100755 index 2b1ffbfe..00000000 --- a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/.gitignore +++ /dev/null @@ -1,36 +0,0 @@ -# Numerous always-ignore extensions -*.diff -*.err -*.orig -*.log -*.rej -*.swo -*.swp -*.zip -*.vi -*~ -*.sass-cache - -# OS or Editor folders -.DS_Store -._* -Thumbs.db -.cache -.project -.settings -.tmproj -*.esproj -nbproject -*.sublime-project -*.sublime-workspace - -# Komodo -*.komodoproject -.komodotools - -# Folders to ignore -.hg -.svn -.CVS -.idea -node_modules diff --git a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/.travis.yml b/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/.travis.yml deleted file mode 100755 index b8e1f172..00000000 --- a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/.travis.yml +++ /dev/null @@ -1,3 +0,0 @@ -language: node_js -node_js: - - 0.6 \ No newline at end of file diff --git a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/LICENSE b/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/LICENSE deleted file mode 100755 index 2bb9ad24..00000000 --- a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/LICENSE +++ /dev/null @@ -1,176 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/README.md b/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/README.md deleted file mode 100755 index f69925ea..00000000 --- a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/README.md +++ /dev/null @@ -1,137 +0,0 @@ -[Twitter Bootstrap](http://twitter.github.com/bootstrap) [![Build Status](https://secure.travis-ci.org/twitter/bootstrap.png)](http://travis-ci.org/twitter/bootstrap) -================= - -Bootstrap provides simple and flexible HTML, CSS, and Javascript for popular user interface components and interactions. In other words, it's a front-end toolkit for faster, more beautiful web development. It's created and maintained by [Mark Otto](http://twitter.com/mdo) and [Jacob Thornton](http://twitter.com/fat) at Twitter. - -To get started, checkout http://twitter.github.com/bootstrap! - - - -Quick start ------------ - -Clone the repo, `git clone git@github.com:twitter/bootstrap.git`, or [download the latest release](https://github.com/twitter/bootstrap/zipball/master). - - - -Versioning ----------- - -For transparency and insight into our release cycle, and for striving to maintain backward compatibility, Bootstrap will be maintained under the Semantic Versioning guidelines as much as possible. - -Releases will be numbered with the follow format: - -`..` - -And constructed with the following guidelines: - -* Breaking backward compatibility bumps the major (and resets the minor and patch) -* New additions without breaking backward compatibility bumps the minor (and resets the patch) -* Bug fixes and misc changes bumps the patch - -For more information on SemVer, please visit http://semver.org/. - - - -Bug tracker ------------ - -Have a bug? Please create an issue here on GitHub! Also, when filing please make sure you're familiar with [necolas's guidelines](https://github.com/necolas/issue-guidelines). thanks! <3 - -https://github.com/twitter/bootstrap/issues - - - -Twitter account ---------------- - -Keep up to date on announcements and more by following Bootstrap on Twitter, [@TwBootstrap](http://twitter.com/TwBootstrap). - - - -Blog ----- - -Read more detailed announcements, discussions, and more on [The Official Twitter Bootstrap Blog](http://blog.getbootstrap.com). - - - -Mailing list ------------- - -Have a question? Ask on our mailing list! - -twitter-bootstrap@googlegroups.com - -http://groups.google.com/group/twitter-bootstrap - - - -IRC ---- - -Server: irc.freenode.net - -Channel: ##twitter-bootstrap (the double ## is not a typo) - - - -Developers ----------- - -We have included a makefile with convenience methods for working with the Bootstrap library. - -+ **dependencies** -Our makefile depends on you having recess, uglify.js, and jshint installed. To install, just run the following command in npm: - -``` -$ npm install recess uglify-js jshint -g -``` - -+ **build** - `make` -Runs the recess compiler to rebuild the `/less` files and compiles the docs pages. Requires recess and uglify-js. Read more in our docs » - -+ **test** - `make test` -Runs jshint and qunit tests headlessly in phantom js (used for ci). Depends on having phatomjs installed. - -+ **watch** - `make watch` -This is a convenience method for watching just Less files and automatically building them whenever you save. Requires the Watchr gem. - - -Contributing ------------- - -Please make all pull requests against wip-* branches. Also, if your unit test contains javascript patches or features - you must include relevant unit tests. Thanks! - - -Authors -------- - -**Mark Otto** - -+ http://twitter.com/mdo -+ http://github.com/markdotto - -**Jacob Thornton** - -+ http://twitter.com/fat -+ http://github.com/fat - - - -Copyright and license ---------------------- - -Copyright 2012 Twitter, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this work except in compliance with the License. -You may obtain a copy of the License in the LICENSE file, or at: - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/img/glyphicons-halflings-white.png b/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/img/glyphicons-halflings-white.png deleted file mode 100755 index 3bf6484a29d8da269f9bc874b25493a45fae3bae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8777 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 c=%yz+Wku{p?}hJ}FfdWj%4dKI|^3?N`*Ur~^l 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 diff --git a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/.jshintrc b/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/.jshintrc deleted file mode 100755 index bbac349e..00000000 --- a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/.jshintrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "validthis": true, - "laxcomma" : true, - "laxbreak" : true, - "browser" : true, - "debug" : true, - "boss" : true, - "expr" : true, - "asi" : true -} \ No newline at end of file diff --git a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/README.md b/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/README.md deleted file mode 100755 index b7927ba6..00000000 --- a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/README.md +++ /dev/null @@ -1,112 +0,0 @@ -## 2.0 BOOTSTRAP JS PHILOSOPHY -These are the high-level design rules which guide the development of Bootstrap's plugin apis. - ---- - -### DATA-ATTRIBUTE API - -We believe you should be able to use all plugins provided by Bootstrap purely through the markup API without writing a single line of JavaScript. This is Bootstrap's first class API. - -We acknowledge that this isn't always the most performant and it may sometimes be desirable to turn this functionality off altogether. Therefore, as of 2.0 we provide the ability to disable the data attribute API by unbinding all events on the body namespaced with `'data-api'`. This looks like this: - - $('body').off('.data-api') - -To target a specific plugin, just include the plugins name as a namespace along with the data-api namespace like this: - - $('body').off('.alert.data-api') - ---- - -### PROGRAMATIC API - -We also believe you should be able to use all plugins provided by Bootstrap purely through the JavaScript API. - -All public APIs should be single, chainable methods, and return the collection acted upon. - - $(".btn.danger").button("toggle").addClass("fat") - -All methods should accept an optional options object, a string which targets a particular method, or null which initiates the default behavior: - - $("#myModal").modal() // initialized with defaults - $("#myModal").modal({ keyboard: false }) // initialized with no keyboard - $("#myModal").modal('show') // initializes and invokes show immediately - ---- - -### OPTIONS - -Options should be sparse and add universal value. We should pick the right defaults. - -All plugins should have a default object which can be modified to affect all instances' default options. The defaults object should be available via `$.fn.plugin.defaults`. - - $.fn.modal.defaults = { … } - -An options definition should take the following form: - - *noun*: *adjective* - describes or modifies a quality of an instance - -Examples: - - backdrop: true - keyboard: false - placement: 'top' - ---- - -### EVENTS - -All events should have an infinitive and past participle form. The infinitive is fired just before an action takes place, the past participle on completion of the action. - - show | shown - hide | hidden - -All infinitive events should provide preventDefault functionality. This provides the abililty to stop the execution of an action. - - $('#myModal').on('show', function (e) { - if (!data) return e.preventDefault() // stops modal from being shown - }) - ---- - -### CONSTRUCTORS - -Each plugin should expose its raw constructor on a `Constructor` property -- accessed in the following way: - - - $.fn.popover.Constructor - ---- - -### DATA ACCESSOR - -Each plugin stores a copy of the invoked class on an object. This class instance can be accessed directly through jQuery's data API like this: - - $('[rel=popover]').data('popover') instanceof $.fn.popover.Constructor - ---- - -### DATA ATTRIBUTES - -Data attributes should take the following form: - -- data-{{verb}}={{plugin}} - defines main interaction -- data-target || href^=# - defined on "control" element (if element controls an element other than self) -- data-{{noun}} - defines class instance options - -Examples: - - // control other targets - data-toggle="modal" data-target="#foo" - data-toggle="collapse" data-target="#foo" data-parent="#bar" - - // defined on element they control - data-spy="scroll" - - data-dismiss="modal" - data-dismiss="alert" - - data-toggle="dropdown" - - data-toggle="button" - data-toggle="buttons-checkbox" - data-toggle="buttons-radio" \ No newline at end of file diff --git a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-alert.js b/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-alert.js deleted file mode 100755 index 57890a9a..00000000 --- a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-alert.js +++ /dev/null @@ -1,90 +0,0 @@ -/* ========================================================== - * bootstrap-alert.js v2.0.4 - * http://twitter.github.com/bootstrap/javascript.html#alerts - * ========================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* ALERT CLASS DEFINITION - * ====================== */ - - var dismiss = '[data-dismiss="alert"]' - , Alert = function (el) { - $(el).on('click', dismiss, this.close) - } - - Alert.prototype.close = function (e) { - var $this = $(this) - , selector = $this.attr('data-target') - , $parent - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 - } - - $parent = $(selector) - - e && e.preventDefault() - - $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) - - $parent.trigger(e = $.Event('close')) - - if (e.isDefaultPrevented()) return - - $parent.removeClass('in') - - function removeElement() { - $parent - .trigger('closed') - .remove() - } - - $.support.transition && $parent.hasClass('fade') ? - $parent.on($.support.transition.end, removeElement) : - removeElement() - } - - - /* ALERT PLUGIN DEFINITION - * ======================= */ - - $.fn.alert = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('alert') - if (!data) $this.data('alert', (data = new Alert(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - $.fn.alert.Constructor = Alert - - - /* ALERT DATA-API - * ============== */ - - $(function () { - $('body').on('click.alert.data-api', dismiss, Alert.prototype.close) - }) - -}(window.jQuery); \ No newline at end of file diff --git a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-button.js b/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-button.js deleted file mode 100755 index 7f187be6..00000000 --- a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-button.js +++ /dev/null @@ -1,96 +0,0 @@ -/* ============================================================ - * bootstrap-button.js v2.0.4 - * http://twitter.github.com/bootstrap/javascript.html#buttons - * ============================================================ - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================ */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* BUTTON PUBLIC CLASS DEFINITION - * ============================== */ - - var Button = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, $.fn.button.defaults, options) - } - - Button.prototype.setState = function (state) { - var d = 'disabled' - , $el = this.$element - , data = $el.data() - , val = $el.is('input') ? 'val' : 'html' - - state = state + 'Text' - data.resetText || $el.data('resetText', $el[val]()) - - $el[val](data[state] || this.options[state]) - - // push to event loop to allow forms to submit - setTimeout(function () { - state == 'loadingText' ? - $el.addClass(d).attr(d, d) : - $el.removeClass(d).removeAttr(d) - }, 0) - } - - Button.prototype.toggle = function () { - var $parent = this.$element.parent('[data-toggle="buttons-radio"]') - - $parent && $parent - .find('.active') - .removeClass('active') - - this.$element.toggleClass('active') - } - - - /* BUTTON PLUGIN DEFINITION - * ======================== */ - - $.fn.button = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('button') - , options = typeof option == 'object' && option - if (!data) $this.data('button', (data = new Button(this, options))) - if (option == 'toggle') data.toggle() - else if (option) data.setState(option) - }) - } - - $.fn.button.defaults = { - loadingText: 'loading...' - } - - $.fn.button.Constructor = Button - - - /* BUTTON DATA-API - * =============== */ - - $(function () { - $('body').on('click.button.data-api', '[data-toggle^=button]', function ( e ) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - $btn.button('toggle') - }) - }) - -}(window.jQuery); \ No newline at end of file diff --git a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-carousel.js b/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-carousel.js deleted file mode 100755 index 551de589..00000000 --- a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-carousel.js +++ /dev/null @@ -1,169 +0,0 @@ -/* ========================================================== - * bootstrap-carousel.js v2.0.4 - * http://twitter.github.com/bootstrap/javascript.html#carousel - * ========================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* CAROUSEL CLASS DEFINITION - * ========================= */ - - var Carousel = function (element, options) { - this.$element = $(element) - this.options = options - this.options.slide && this.slide(this.options.slide) - this.options.pause == 'hover' && this.$element - .on('mouseenter', $.proxy(this.pause, this)) - .on('mouseleave', $.proxy(this.cycle, this)) - } - - Carousel.prototype = { - - cycle: function (e) { - if (!e) this.paused = false - this.options.interval - && !this.paused - && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) - return this - } - - , to: function (pos) { - var $active = this.$element.find('.active') - , children = $active.parent().children() - , activePos = children.index($active) - , that = this - - if (pos > (children.length - 1) || pos < 0) return - - if (this.sliding) { - return this.$element.one('slid', function () { - that.to(pos) - }) - } - - if (activePos == pos) { - return this.pause().cycle() - } - - return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos])) - } - - , pause: function (e) { - if (!e) this.paused = true - clearInterval(this.interval) - this.interval = null - return this - } - - , next: function () { - if (this.sliding) return - return this.slide('next') - } - - , prev: function () { - if (this.sliding) return - return this.slide('prev') - } - - , slide: function (type, next) { - var $active = this.$element.find('.active') - , $next = next || $active[type]() - , isCycling = this.interval - , direction = type == 'next' ? 'left' : 'right' - , fallback = type == 'next' ? 'first' : 'last' - , that = this - , e = $.Event('slide') - - this.sliding = true - - isCycling && this.pause() - - $next = $next.length ? $next : this.$element.find('.item')[fallback]() - - if ($next.hasClass('active')) return - - if ($.support.transition && this.$element.hasClass('slide')) { - this.$element.trigger(e) - if (e.isDefaultPrevented()) return - $next.addClass(type) - $next[0].offsetWidth // force reflow - $active.addClass(direction) - $next.addClass(direction) - this.$element.one($.support.transition.end, function () { - $next.removeClass([type, direction].join(' ')).addClass('active') - $active.removeClass(['active', direction].join(' ')) - that.sliding = false - setTimeout(function () { that.$element.trigger('slid') }, 0) - }) - } else { - this.$element.trigger(e) - if (e.isDefaultPrevented()) return - $active.removeClass('active') - $next.addClass('active') - this.sliding = false - this.$element.trigger('slid') - } - - isCycling && this.cycle() - - return this - } - - } - - - /* CAROUSEL PLUGIN DEFINITION - * ========================== */ - - $.fn.carousel = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('carousel') - , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option) - if (!data) $this.data('carousel', (data = new Carousel(this, options))) - if (typeof option == 'number') data.to(option) - else if (typeof option == 'string' || (option = options.slide)) data[option]() - else if (options.interval) data.cycle() - }) - } - - $.fn.carousel.defaults = { - interval: 5000 - , pause: 'hover' - } - - $.fn.carousel.Constructor = Carousel - - - /* CAROUSEL DATA-API - * ================= */ - - $(function () { - $('body').on('click.carousel.data-api', '[data-slide]', function ( e ) { - var $this = $(this), href - , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 - , options = !$target.data('modal') && $.extend({}, $target.data(), $this.data()) - $target.carousel(options) - e.preventDefault() - }) - }) - -}(window.jQuery); \ No newline at end of file diff --git a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-collapse.js b/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-collapse.js deleted file mode 100755 index fbc915b9..00000000 --- a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-collapse.js +++ /dev/null @@ -1,157 +0,0 @@ -/* ============================================================= - * bootstrap-collapse.js v2.0.4 - * http://twitter.github.com/bootstrap/javascript.html#collapse - * ============================================================= - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================ */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* COLLAPSE PUBLIC CLASS DEFINITION - * ================================ */ - - var Collapse = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, $.fn.collapse.defaults, options) - - if (this.options.parent) { - this.$parent = $(this.options.parent) - } - - this.options.toggle && this.toggle() - } - - Collapse.prototype = { - - constructor: Collapse - - , dimension: function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - , show: function () { - var dimension - , scroll - , actives - , hasData - - if (this.transitioning) return - - dimension = this.dimension() - scroll = $.camelCase(['scroll', dimension].join('-')) - actives = this.$parent && this.$parent.find('> .accordion-group > .in') - - if (actives && actives.length) { - hasData = actives.data('collapse') - if (hasData && hasData.transitioning) return - actives.collapse('hide') - hasData || actives.data('collapse', null) - } - - this.$element[dimension](0) - this.transition('addClass', $.Event('show'), 'shown') - this.$element[dimension](this.$element[0][scroll]) - } - - , hide: function () { - var dimension - if (this.transitioning) return - dimension = this.dimension() - this.reset(this.$element[dimension]()) - this.transition('removeClass', $.Event('hide'), 'hidden') - this.$element[dimension](0) - } - - , reset: function (size) { - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - [dimension](size || 'auto') - [0].offsetWidth - - this.$element[size !== null ? 'addClass' : 'removeClass']('collapse') - - return this - } - - , transition: function (method, startEvent, completeEvent) { - var that = this - , complete = function () { - if (startEvent.type == 'show') that.reset() - that.transitioning = 0 - that.$element.trigger(completeEvent) - } - - this.$element.trigger(startEvent) - - if (startEvent.isDefaultPrevented()) return - - this.transitioning = 1 - - this.$element[method]('in') - - $.support.transition && this.$element.hasClass('collapse') ? - this.$element.one($.support.transition.end, complete) : - complete() - } - - , toggle: function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - } - - - /* COLLAPSIBLE PLUGIN DEFINITION - * ============================== */ - - $.fn.collapse = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('collapse') - , options = typeof option == 'object' && option - if (!data) $this.data('collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.collapse.defaults = { - toggle: true - } - - $.fn.collapse.Constructor = Collapse - - - /* COLLAPSIBLE DATA-API - * ==================== */ - - $(function () { - $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) { - var $this = $(this), href - , target = $this.attr('data-target') - || e.preventDefault() - || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 - , option = $(target).data('collapse') ? 'toggle' : $this.data() - $(target).collapse(option) - }) - }) - -}(window.jQuery); \ No newline at end of file diff --git a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-dropdown.js b/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-dropdown.js deleted file mode 100755 index 454a9684..00000000 --- a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-dropdown.js +++ /dev/null @@ -1,100 +0,0 @@ -/* ============================================================ - * bootstrap-dropdown.js v2.0.4 - * http://twitter.github.com/bootstrap/javascript.html#dropdowns - * ============================================================ - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================ */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* DROPDOWN CLASS DEFINITION - * ========================= */ - - var toggle = '[data-toggle="dropdown"]' - , Dropdown = function (element) { - var $el = $(element).on('click.dropdown.data-api', this.toggle) - $('html').on('click.dropdown.data-api', function () { - $el.parent().removeClass('open') - }) - } - - Dropdown.prototype = { - - constructor: Dropdown - - , toggle: function (e) { - var $this = $(this) - , $parent - , selector - , isActive - - if ($this.is('.disabled, :disabled')) return - - selector = $this.attr('data-target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 - } - - $parent = $(selector) - $parent.length || ($parent = $this.parent()) - - isActive = $parent.hasClass('open') - - clearMenus() - - if (!isActive) $parent.toggleClass('open') - - return false - } - - } - - function clearMenus() { - $(toggle).parent().removeClass('open') - } - - - /* DROPDOWN PLUGIN DEFINITION - * ========================== */ - - $.fn.dropdown = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('dropdown') - if (!data) $this.data('dropdown', (data = new Dropdown(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - $.fn.dropdown.Constructor = Dropdown - - - /* APPLY TO STANDARD DROPDOWN ELEMENTS - * =================================== */ - - $(function () { - $('html').on('click.dropdown.data-api', clearMenus) - $('body') - .on('click.dropdown', '.dropdown form', function (e) { e.stopPropagation() }) - .on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle) - }) - -}(window.jQuery); \ No newline at end of file diff --git a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-modal.js b/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-modal.js deleted file mode 100755 index 38fd0c84..00000000 --- a/middleman-core/fixtures/twitter-bootstrap-app/source/twitter-bootstrap-ebc6935/js/bootstrap-modal.js +++ /dev/null @@ -1,218 +0,0 @@ -/* ========================================================= - * bootstrap-modal.js v2.0.4 - * http://twitter.github.com/bootstrap/javascript.html#modals - * ========================================================= - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================= */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* MODAL CLASS DEFINITION - * ====================== */ - - var Modal = function (content, options) { - this.options = options - this.$element = $(content) - .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this)) - } - - Modal.prototype = { - - constructor: Modal - - , toggle: function () { - return this[!this.isShown ? 'show' : 'hide']() - } - - , show: function () { - var that = this - , e = $.Event('show') - - this.$element.trigger(e) - - if (this.isShown || e.isDefaultPrevented()) return - - $('body').addClass('modal-open') - - this.isShown = true - - escape.call(this) - backdrop.call(this, function () { - var transition = $.support.transition && that.$element.hasClass('fade') - - if (!that.$element.parent().length) { - that.$element.appendTo(document.body) //don't move modals dom position - } - - that.$element - .show() - - if (transition) { - that.$element[0].offsetWidth // force reflow - } - - that.$element.addClass('in') - - transition ? - that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) : - that.$element.trigger('shown') - - }) - } - - , hide: function (e) { - e && e.preventDefault() - - var that = this - - e = $.Event('hide') - - this.$element.trigger(e) - - if (!this.isShown || e.isDefaultPrevented()) return - - this.isShown = false - - $('body').removeClass('modal-open') - - escape.call(this) - - this.$element.removeClass('in') - - $.support.transition && this.$element.hasClass('fade') ? - hideWithTransition.call(this) : - hideModal.call(this) - } - - } - - - /* MODAL PRIVATE METHODS - * ===================== */ - - function hideWithTransition() { - var that = this - , timeout = setTimeout(function () { - that.$element.off($.support.transition.end) - hideModal.call(that) - }, 500) - - this.$element.one($.support.transition.end, function () { - clearTimeout(timeout) - hideModal.call(that) - }) - } - - function hideModal(that) { - this.$element - .hide() - .trigger('hidden') - - backdrop.call(this) - } - - function backdrop(callback) { - var that = this - , animate = this.$element.hasClass('fade') ? 'fade' : '' - - if (this.isShown && this.options.backdrop) { - var doAnimate = $.support.transition && animate - - this.$backdrop = $('