remove_hooks
Thomas Reynolds 2014-11-19 09:04:56 -08:00
commit d8e8b06cb6
28 changed files with 334 additions and 121 deletions

View File

@ -41,6 +41,8 @@ AssignmentInCondition:
Enabled: false
CyclomaticComplexity:
Enabled: false
AbcSize:
Enabled: false
HandleExceptions:
Enabled: false
EndAlignment:

View File

@ -5,6 +5,10 @@ before_install: git submodule update --init --recursive
rvm:
- ruby-head
- jruby-19mode
- 2.2
- 2.1.5
- 2.1.4
- 2.1.3
- 2.1.2
- 2.1.1
- 2.1.0

View File

@ -29,6 +29,23 @@ master
* Remove old module-style extension support
* Placed all `config.rb` evaluation inside the `ConfigContext` class
3.3.7
===
* Update new project template Gemfile to use HTTPS by default. #1372
3.3.6
===
* Use full paths instead of relative for `listen` gem. Fixes #1374
* Add force option to "middleman init". #1369
* Configuration addition for compass 1 compatibility.
* Catch File read exceptions in frontmatter.
* Remove duplicate attr_accessor. Closes #1352
* Update sass dependency to >= 3.4.0.
* Update compass dependency to >= 1.0.0, < 2.0.0
* Accept pandoc-style YAML frontmatter. #1350
* Add webp to image type lists.
3.3.5
===

View File

@ -43,6 +43,8 @@ end
desc 'Run tests for all middleman gems'
task :test do
Rake::Task['rubocop'].invoke
GEM_PATHS.each do |g|
Dir.chdir("#{File.join(ROOT, g)}") { sh "#{Gem.ruby} -S rake test" }
end

View File

@ -1,6 +1,6 @@
# If you have OpenSSL installed, we recommend updating
# the following line to use "https"
source 'http://rubygems.org'
# If you do not have OpenSSL installed, update
# the following line to use "http://" instead
source 'https://rubygems.org'
# Specify your gem's dependencies in <%= name %>.gemspec
gemspec

View File

@ -1,5 +1,5 @@
Feature: Assets get a file hash appended to their and references to them are updated
Scenario: Hashed-asset files are produced, and HTML, CSS, and JavaScript gets rewritten to reference the new files
Scenario: Hashed-asset files are produced, and HTML, CSS, JSON and JavaScript gets rewritten to reference the new files
Given a successfully built app at "asset-hash-app"
When I cd to "build"
Then the following files should exist:
@ -8,12 +8,16 @@ Feature: Assets get a file hash appended to their and references to them are upd
| favicon.ico |
| images/100px-1242c368.png |
| images/100px-5fd6fb90.jpg |
| images/200px-c11eb203.jpg |
| images/300px-59adce76.jpg |
| images/100px-5fd6fb90.gif |
| javascripts/application-1d8d5276.js |
| stylesheets/site-7474cadd.css |
| index.html |
| subdir/index.html |
| other/index.html |
| api.json |
| subdir/api.json |
And the following files should not exist:
| images/100px.png |
| images/100px.jpg |
@ -31,11 +35,20 @@ Feature: Assets get a file hash appended to their and references to them are upd
And the file "index.html" should contain 'src="javascripts/application-1d8d5276.js"'
And the file "index.html" should contain 'src="images/100px-5fd6fb90.jpg"'
And the file "subdir/index.html" should contain 'href="../stylesheets/site-7474cadd.css"'
And the file "index.html" should contain 'srcset="images/100px-5fd6fb90.jpg 1x, images/200px-c11eb203.jpg 2x, images/300px-59adce76.jpg 3x"'
And the file "index.html" should contain 'src="images/100px-5fd6fb90.gif"'
And the file "index.html" should contain 'src="images/100px-1242c368.png"'
And the file "subdir/index.html" should contain 'src="../javascripts/application-1d8d5276.js"'
And the file "subdir/index.html" should contain 'src="../images/100px-5fd6fb90.jpg"'
And the file "other/index.html" should contain 'href="../stylesheets/site-7474cadd.css"'
And the file "other/index.html" should contain 'src="../javascripts/application-1d8d5276.js"'
And the file "other/index.html" should contain 'src="../images/100px-5fd6fb90.jpg"'
And the file "api.json" should contain 'images/100px-5fd6fb90.gif'
And the file "api.json" should contain 'images/100px-5fd6fb90.jpg'
And the file "api.json" should contain 'images/100px-1242c368.png'
And the file "subdir/api.json" should contain 'images/100px-5fd6fb90.gif'
And the file "subdir/api.json" should contain 'images/100px-5fd6fb90.jpg'
And the file "subdir/api.json" should contain 'images/100px-1242c368.png'
Scenario: Hashed assets work in preview server
Given the Server is running at "asset-hash-app"
@ -44,6 +57,7 @@ Feature: Assets get a file hash appended to their and references to them are upd
And I should see 'href="stylesheets/site-7474cadd.css"'
And I should see 'src="javascripts/application-1d8d5276.js"'
And I should see 'src="images/100px-5fd6fb90.jpg"'
And I should see 'srcset="images/100px-5fd6fb90.jpg 1x, images/200px-c11eb203.jpg 2x, images/300px-59adce76.jpg 3x"'
When I go to "/subdir/"
Then I should see 'href="../stylesheets/site-7474cadd.css"'
And I should see 'src="../javascripts/application-1d8d5276.js"'
@ -55,10 +69,15 @@ Feature: Assets get a file hash appended to their and references to them are upd
When I go to "/javascripts/application-1d8d5276.js"
Then I should see "img.src = '/images/100px-5fd6fb90.jpg'"
When I go to "/stylesheets/site-7474cadd.css"
Then I should see:
"""
background-image: url("../images/100px-5fd6fb90.jpg")
"""
Then I should see 'background-image: url("../images/100px-5fd6fb90.jpg")'
When I go to "/api.json"
Then I should see 'images/100px-5fd6fb90.gif'
And I should see 'images/100px-5fd6fb90.jpg'
And I should see 'images/100px-1242c368.png'
When I go to "/subdir/api.json"
Then I should see 'images/100px-5fd6fb90.gif'
And I should see 'images/100px-5fd6fb90.jpg'
And I should see 'images/100px-1242c368.png'
Scenario: Enabling an asset host still produces hashed files and references
Given the Server is running at "asset-hash-host-app"
@ -71,9 +90,6 @@ Feature: Assets get a file hash appended to their and references to them are upd
When I go to "/other/"
Then I should see 'href="http://middlemanapp.com/stylesheets/site-1fdf4fb5.css"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"'
# Asset helpers don't appear to work from Compass right now
# When I go to "/stylesheets/site-e5a31a3e.css"
# Then I should see "background-image: url('http://middlemanapp.com/images/100px-5fd6fb90.jpg')"
Scenario: The asset hash should change when a SASS partial changes
Given the Server is running at "asset-hash-app"
@ -138,6 +154,8 @@ Feature: Assets get a file hash appended to their and references to them are upd
| index.html |
| subdir/index.html |
| other/index.html |
| api.json |
| subdir/api.json |
And the following files should not exist:
| images/100px-1242c368.png |
| images/100px-5fd6fb90.jpg |

View File

@ -16,4 +16,91 @@ Feature: Templates should be chainable
And the file "index.html" should contain "Title</h1>"
And the file "index.html" should contain "Subtitle</h2>"
And the file "index.html" should contain "Sup</h3>"
And the file "index.html" should contain "Sup</h3>"
Scenario: Partials are parsed by multiple template engines: Outer template has .erb and inner .md.erb
Given a fixture app "partial-chained_templates-app"
And a template named "my_template.html.erb" with:
"""
<h1>My Template</h1>
<%= partial 'my_partial' %>
"""
And a template named "my_partial.html.md.erb" with:
"""
## My Partial
<%= 'hello world' %>
"""
And the Server is running
When I go to "/my_template.html"
Then I should see:
"""
<h1>My Template</h1>
"""
Then I should see:
"""
<h2 id="my-partial">My Partial</h2>
"""
Then I should see:
"""
<p>hello world</p>
"""
Scenario: Partials are parsed by multiple template engines: Outer template has .md.erb and inner .md.erb
Given a fixture app "partial-chained_templates-app"
And a template named "my_template.html.md.erb" with:
"""
# My Template
<%= partial 'my_partial' %>
"""
And a template named "my_partial.html.md.erb" with:
"""
## My Partial
<%= 'hello world' %>
"""
And the Server is running
When I go to "/my_template.html"
Then I should see:
"""
<h1 id="my-template">My Template</h1>
"""
Then I should see:
"""
<h2 id="my-partial">My Partial</h2>
"""
Then I should see:
"""
<p>hello world</p>
"""
Scenario: Partials are parsed by multiple template engines: Outer template has .md.erb, and inner .erb
Given a fixture app "partial-chained_templates-app"
And a template named "my_template.html.md.erb" with:
"""
# My Template
<%= partial 'my_partial' %>
"""
And a template named "my_partial.html.erb" with:
"""
<h2>My Partial</h2>
<%= 'hello world' %>
"""
And the Server is running
When I go to "/my_template.html"
Then I should see:
"""
<h1 id="my-template">My Template</h1>
"""
Then I should see:
"""
<h2>My Partial</h2>
"""
Then I should see:
"""
<p>hello world</p>
"""

View File

@ -37,21 +37,3 @@ Feature: Middleman CLI
Scenario: Create a new project (alias n)
When I run `middleman n MY_PROJECT`
Then a directory named "MY_PROJECT" should exist
# Scenario: Create a new HTML5 project
# When I run `middleman init MY_PROJECT --template=html5`
# Then a directory named "MY_PROJECT" should exist
# When I cd to "MY_PROJECT"
# Then the following files should exist:
# | config.rb |
# | Gemfile |
# Then the following files should not exist:
# | config.ru |
# And the file "config.rb" should contain "set :js_dir, 'js'"
# Then a directory named "source" should exist
# When I cd to "source"
# Then the following files should exist:
# | index.html.erb |
# | layouts/layout.erb |
# | humans.txt |
# | js/main.js |

View File

@ -0,0 +1,33 @@
Feature: Honour working directory
Honour the working directory during testing
In order to support helpers which work with the current directories
Scenario: Set working directory for helpers in tests
Given a fixture app "empty-app"
And a file named "source/index.html.erb" with:
"""
<%= Dir.getwd %>
"""
And the Server is running
When I go to "/index.html"
Then I should see:
"""
aruba
"""
Scenario: Set working directory for config.rb in tests
Given a fixture app "empty-app"
And a file named "config.rb" with:
"""
set :my_working_directory, Dir.getwd
"""
And a file named "source/index.html.erb" with:
"""
<%= config[:my_working_directory] %>
"""
And the Server is running
When I go to "/index.html"
Then I should see:
"""
aruba
"""

View File

@ -0,0 +1 @@
<%= {gif: image_path('100px.gif'), jpg: image_path('100px.jpg'), png: image_path('100px.png')}.to_json %>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -3,7 +3,7 @@
<% end %>
<h2>Image url:</h2>
<img src="<%= image_path('100px.jpg') %>">
<img src="<%= image_path('100px.jpg') %>" srcset="<%= image_path('100px.jpg') %> 1x, <%= image_path('200px.jpg') %> 2x, <%= image_path('300px.jpg') %> 3x">
<h2>Ignored path:</h2>
<link rel="apple-touch-icon" href="apple-touch-icon.png">

View File

@ -0,0 +1 @@
<%= {gif: image_path('100px.gif'), jpg: image_path('100px.jpg'), png: image_path('100px.png')}.to_json %>

View File

@ -1,10 +1,5 @@
Default: <%= data.data.title %>
Data 1: <%= data.data1.title %>
Data 2: <%= data.data2.title %>
<<<<<<< HEAD
Override in Two: <%= data.two.title %>
Override in One: <%= data.one.title %>
=======
Override in One: <%= data.one.title %>
Override in Two: <%= data.two.title %>
>>>>>>> Add external command support

View File

@ -163,7 +163,7 @@ module Middleman
layout: proc { |file, _sitemap_app|
file[:relative_path].to_s.start_with?('layout.') ||
file[:relative_path].to_s.start_with?('layouts/')
file[:relative_path].to_s.start_with?('layouts/')
}
}, 'Callbacks that can exclude paths from the sitemap'

View File

@ -11,7 +11,7 @@ class Padrino::Helpers::OutputHelpers::ErbHandler
raw = block.call(*args)
captured = template.instance_variable_get(:@_out_buf)
self.output_buffer = buf_was
engine_matches?(block) ? captured : raw
engine_matches?(block) && !captured.empty? ? captured : raw
end
end

View File

@ -90,7 +90,14 @@ module Middleman::CoreExtensions
return [data, nil] if ::Middleman::Util.binary?(full_path)
content = File.read(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:/

View File

@ -59,12 +59,12 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
if lang_suffix
super(suffixed_partial_name) ||
super(File.join(locals_dir, suffixed_partial_name)) ||
super(partials_path) ||
super
super(File.join(locals_dir, suffixed_partial_name)) ||
super(partials_path) ||
super
else
super(partials_path) ||
super
super
end
end
end

View File

@ -64,8 +64,8 @@ module Middleman
block
elsif extension_class && extension_class.ancestors.include?(::Middleman::Extension)
extension_class
else
raise 'You must provide a Middleman::Extension or a block that returns a Middleman::Extension'
else
raise 'You must provide a Middleman::Extension or a block that returns a Middleman::Extension'
end
return unless options[:auto_activate]

View File

@ -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 : 'Dynamic'
props['Source File'] = @resource.source_file ? @resource.source_file[:full_path].to_s.sub(/^#{Regexp.escape(ENV['MM_ROOT'] + '/')}/, '') : 'Dynamic'
data = @resource.data
props['Data'] = data.inspect unless data.empty?

View File

@ -84,7 +84,7 @@ module Middleman
def globally_ignored?(file)
@ignores.values.any? do |descriptor|
((descriptor[:type] == :all) || file[:types].include?(descriptor[:type])) &&
matches?(descriptor[:validator], file)
matches?(descriptor[:validator], file)
end
end
@ -169,11 +169,11 @@ module Middleman
Contract Symbol, String, Maybe[Bool] => Maybe[SourceFile]
def find(type, path, glob=false)
watchers
.lazy
.select { |d| d.type == type }
.map { |d| d.find(path, glob) }
.reject(&:nil?)
.first
.lazy
.select { |d| d.type == type }
.map { |d| d.find(path, glob) }
.reject(&:nil?)
.first
end
# Check if a file for a given type exists.
@ -184,9 +184,9 @@ module Middleman
Contract Symbol, String => Bool
def exists?(type, path)
watchers
.lazy
.select { |d| d.type == type }
.any? { |d| d.exists?(path) }
.lazy
.select { |d| d.type == type }
.any? { |d| d.exists?(path) }
end
# Check if a file for a given type exists.
@ -197,8 +197,8 @@ module Middleman
Contract SetOf[Symbol], String => Maybe[HANDLER]
def watcher_for_path(types, path)
watchers
.select { |d| types.include?(d.type) }
.find { |d| d.exists?(path) }
.select { |d| types.include?(d.type) }
.find { |d| d.exists?(path) }
end
# Manually poll all watchers for new content.

View File

@ -104,7 +104,6 @@ module Middleman
return nil if p.absolute? && !p.to_s.start_with?(@directory.to_s)
p = @directory + p if p.relative?
if glob
@extensionless_files[p]
else
@ -211,25 +210,25 @@ module Middleman
Contract ArrayOf[Pathname], ArrayOf[Pathname] => Any
def update(updated_paths, removed_paths)
valid_updates = updated_paths
.lazy
.map(&method(:path_to_source_file))
.select(&method(:valid?))
.to_a
.each do |f|
add_file_to_cache(f)
logger.debug "== Change (#{f[:types].inspect}): #{f[:relative_path]}"
end
.lazy
.map(&method(:path_to_source_file))
.select(&method(:valid?))
.to_a
.each do |f|
add_file_to_cache(f)
logger.debug "== Change (#{f[:types].inspect}): #{f[:relative_path]}"
end
valid_removes = removed_paths
.lazy
.select(&@files.method(:key?))
.map(&@files.method(:[]))
.select(&method(:valid?))
.to_a
.each do |f|
remove_file_from_cache(f)
logger.debug "== Deletion (#{f[:types].inspect}): #{f[:relative_path]}"
end
.lazy
.select(&@files.method(:key?))
.map(&@files.method(:[]))
.select(&method(:valid?))
.to_a
.each do |f|
remove_file_from_cache(f)
logger.debug "== Deletion (#{f[:types].inspect}): #{f[:relative_path]}"
end
run_callbacks(
@on_change_callbacks,
@ -240,12 +239,19 @@ module Middleman
def add_file_to_cache(f)
@files[f[:full_path]] = f
@extensionless_files[f[:full_path].sub_ext('.*')] = f
@extensionless_files[strip_extensions(f[:full_path])] = f
end
def remove_file_from_cache(f)
@files.delete(f[:full_path])
@extensionless_files.delete(f[:full_path].sub_ext('.*'))
@extensionless_files.delete(strip_extensions(f[:full_path]))
end
def strip_extensions(p)
while ::Tilt[p.to_s] || p.extname === '.html'
p = p.sub_ext('')
end
Pathname(p.to_s + '.*')
end
# Check if this watcher should care about a file.
@ -255,8 +261,8 @@ module Middleman
Contract IsA['Middleman::SourceFile'] => Bool
def valid?(file)
@validator.call(file) &&
!globally_ignored?(file) &&
!@ignored.call(file)
!globally_ignored?(file) &&
!@ignored.call(file)
end
# Convert a path to a file resprentation.

View File

@ -33,6 +33,7 @@ end
Given /^the Server is running$/ do
root_dir = File.expand_path(current_dir)
if File.exists?(File.join(root_dir, 'source'))
ENV['MM_SOURCE'] = 'source'
else
@ -43,12 +44,14 @@ Given /^the Server is running$/ do
initialize_commands = @initialize_commands || []
@server_inst = ::Middleman::Application.new do
config[:watcher_disable] = true
config[:show_exceptions] = false
in_current_dir do
@server_inst = ::Middleman::Application.new do
config[:watcher_disable] = true
config[:show_exceptions] = false
initialize_commands.each do |p|
instance_exec(&p)
initialize_commands.each do |p|
instance_exec(&p)
end
end
end
@ -61,54 +64,82 @@ Given /^the Server is running at "([^\"]*)"$/ do |app_path|
step %Q{the Server is running}
end
Given /^a template named "([^\"]*)" with:$/ do |name, string|
step %Q{a file named "source/#{name}" with:}, string
end
When /^I go to "([^\"]*)"$/ do |url|
@last_response = @browser.get(URI.escape(url))
in_current_dir do
@last_response = @browser.get(URI.escape(url))
end
end
Then /^going to "([^\"]*)" should not raise an exception$/ do |url|
last_response = nil
expect {
last_response = @browser.get(URI.escape(url))
}.to_not raise_error
@last_response = last_response
in_current_dir do
last_response = nil
expect {
last_response = @browser.get(URI.escape(url))
}.to_not raise_error
@last_response = last_response
end
end
Then /^the content type should be "([^\"]*)"$/ do |expected|
expect(@last_response.content_type).to start_with(expected)
in_current_dir do
expect(@last_response.content_type).to start_with(expected)
end
end
Then /^I should see "([^\"]*)"$/ do |expected|
expect(@last_response.body).to include(expected)
in_current_dir do
expect(@last_response.body).to include(expected)
end
end
Then /^I should see '([^\']*)'$/ do |expected|
expect(@last_response.body).to include(expected)
in_current_dir do
expect(@last_response.body).to include(expected)
end
end
Then /^I should see:$/ do |expected|
expect(@last_response.body).to include(expected)
in_current_dir do
expect(@last_response.body).to include(expected)
end
end
Then /^I should not see "([^\"]*)"$/ do |expected|
expect(@last_response.body).to_not include(expected)
in_current_dir do
expect(@last_response.body).to_not include(expected)
end
end
Then /^I should see content matching %r{(.*)}$/ do |expected|
expect(@last_response.body).to match(expected)
in_current_dir do
expect(@last_response.body).to match(expected)
end
end
Then /^I should not see content matching %r{(.*)}$/ do |expected|
expect(@last_response.body).to_not match(expected)
in_current_dir do
expect(@last_response.body).to_not match(expected)
end
end
Then /^I should not see:$/ do |expected|
expect(@browser.last_response.body).to_not include(expected.chomp)
in_current_dir do
expect(@browser.last_response.body).to_not include(expected.chomp)
end
end
Then /^the status code should be "([^\"]*)"$/ do |expected|
expect(@browser.last_response.status).to eq expected.to_i
in_current_dir do
expect(@browser.last_response.status).to eq expected.to_i
end
end
Then /^I should see "([^\"]*)" lines$/ do |lines|
expect(@last_response.body.chomp.split($/).length).to eq(lines.to_i)
in_current_dir do
expect(@last_response.body.chomp.split($/).length).to eq(lines.to_i)
end
end

View File

@ -30,7 +30,7 @@ module Middleman
# @param [Middleman::Application] app
# @param [Hash] locs
# @param [Hash] opts
def initialize(app, locs={}.freeze, opts={}.freeze)
def initialize(app, locs={}, opts={})
@app = app
@locs = locs
@opts = opts
@ -114,7 +114,7 @@ module Middleman
opts = options.dup
locs = opts.delete(:locals)
render_file(partial_file, locs.freeze, opts.freeze, &block)
render_file(partial_file, locs, opts, &block)
end
end
@ -163,8 +163,28 @@ module Middleman
# @return [String] The resulting content string.
Contract IsA['Middleman::SourceFile'], Hash, Hash, Proc => String
def render_file(file, locs, opts, &block)
file_renderer = ::Middleman::FileRenderer.new(@app, file[:relative_path].to_s)
file_renderer.render(locs, opts, self, &block)
_render_with_all_renderers(file[:relative_path].to_s, locs, self, opts, &block)
end
def _render_with_all_renderers(path, locs, context, opts, &block)
# Keep rendering template until we've used up all extensions. This
# handles cases like `style.css.sass.erb`
content = nil
while ::Tilt[path]
begin
opts[:template_body] = content if content
content_renderer = ::Middleman::FileRenderer.new(@app, path)
content = content_renderer.render(locs, opts, context, &block)
path = File.basename(path, File.extname(path))
rescue LocalJumpError
raise "Tried to render a layout (calls yield) at #{path} like it was a template. Non-default layouts need to be in #{@app.config[:source]}/#{@app.config[:layouts_dir]}."
end
end
content
end
def current_path

View File

@ -42,7 +42,7 @@ module Middleman
# @param [Hash] opts
# @return [String]
Contract Hash, Hash => String
def render(locs={}, opts={})
def render(locs={}, opts={}, &block)
path = @path.dup
locals = locs.dup.freeze
options = opts.dup
@ -61,21 +61,7 @@ module Middleman
# TODO: Only for HAML files
context.init_haml_helpers if context.respond_to?(:init_haml_helpers)
# Keep rendering template until we've used up all extensions. This
# handles cases like `style.css.sass.erb`
content = nil
while ::Tilt[path]
begin
options[:template_body] = content if content
content_renderer = ::Middleman::FileRenderer.new(@app, path)
content = content_renderer.render(locals, options, context)
path = File.basename(path, File.extname(path))
rescue LocalJumpError
raise "Tried to render a layout (calls yield) at #{path} like it was a template. Non-default layouts need to be in #{source}/#{@app.config[:layouts_dir]}."
end
end
content = _render_with_all_renderers(path, locs, context, opts, &block)
# If we need a layout and have a layout, use it
if layout_file = fetch_layout(engine, options)
@ -93,6 +79,27 @@ module Middleman
protected
def _render_with_all_renderers(path, locs, context, opts, &block)
# Keep rendering template until we've used up all extensions. This
# handles cases like `style.css.sass.erb`
content = nil
while ::Tilt[path]
begin
opts[:template_body] = content if content
content_renderer = ::Middleman::FileRenderer.new(@app, path)
content = content_renderer.render(locs, opts, context, &block)
path = File.basename(path, File.extname(path))
rescue LocalJumpError
raise "Tried to render a layout (calls yield) at #{path} like it was a template. Non-default layouts need to be in #{@app.config[:source]}/#{@app.config[:layouts_dir]}."
end
end
content
end
# Find a layout for a given engine
#
# @param [Symbol] engine

View File

@ -317,7 +317,7 @@ module Middleman
Contract String, String, ArrayOf[String], Proc => String
def rewrite_paths(body, _path, exts, &_block)
body.dup.gsub(/([=\'\"\(]\s*)([^\s\'\"\)]+(#{Regexp.union(exts)}))/) do |match|
body.dup.gsub(/([=\'\"\(,]\s*)([^\s\'\"\)]+(#{Regexp.union(exts)}))/) do |match|
opening_character = $1
asset_path = $2