middleman-core 4.1.0.rc.1 → 4.1.0.rc.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/features/asset_hash.feature +44 -6
  4. data/features/asset_host.feature +1 -0
  5. data/features/automatic_image_sizes.feature +18 -5
  6. data/fixtures/asset-hash-host-app/source/index.html.erb +1 -1
  7. data/fixtures/asset-host-app/config.rb +1 -0
  8. data/fixtures/asset-host-app/source/asset_host.html.erb +9 -0
  9. data/fixtures/automatic-image-size-app/source/markdown-sizes.html.markdown +1 -0
  10. data/lib/middleman-core/application.rb +68 -58
  11. data/lib/middleman-core/builder.rb +24 -18
  12. data/lib/middleman-core/callback_manager.rb +8 -1
  13. data/lib/middleman-core/contracts.rb +13 -102
  14. data/lib/middleman-core/core_extensions.rb +6 -0
  15. data/lib/middleman-core/core_extensions/collections/lazy_step.rb +1 -1
  16. data/lib/middleman-core/core_extensions/data.rb +3 -2
  17. data/lib/middleman-core/core_extensions/default_helpers.rb +5 -5
  18. data/lib/middleman-core/core_extensions/external_helpers.rb +6 -11
  19. data/lib/middleman-core/core_extensions/file_watcher.rb +1 -1
  20. data/lib/middleman-core/core_extensions/front_matter.rb +1 -0
  21. data/lib/middleman-core/core_extensions/i18n.rb +4 -4
  22. data/lib/middleman-core/core_extensions/inline_url_rewriter.rb +150 -0
  23. data/lib/middleman-core/core_extensions/routing.rb +22 -28
  24. data/lib/middleman-core/core_extensions/show_exceptions.rb +1 -7
  25. data/lib/middleman-core/extension.rb +19 -2
  26. data/lib/middleman-core/extension_manager.rb +2 -0
  27. data/lib/middleman-core/extensions.rb +12 -0
  28. data/lib/middleman-core/extensions/asset_hash.rb +21 -20
  29. data/lib/middleman-core/extensions/asset_host.rb +9 -10
  30. data/lib/middleman-core/extensions/automatic_image_sizes.rb +1 -1
  31. data/lib/middleman-core/extensions/cache_buster.rb +6 -12
  32. data/lib/middleman-core/extensions/gzip.rb +2 -2
  33. data/lib/middleman-core/extensions/lorem.rb +1 -1
  34. data/lib/middleman-core/extensions/minify_css.rb +2 -2
  35. data/lib/middleman-core/extensions/minify_javascript.rb +2 -2
  36. data/lib/middleman-core/extensions/relative_assets.rb +6 -12
  37. data/lib/middleman-core/preview_server.rb +11 -9
  38. data/lib/middleman-core/preview_server/server_hostname.rb +2 -2
  39. data/lib/middleman-core/rack.rb +1 -1
  40. data/lib/middleman-core/renderers/kramdown.rb +1 -1
  41. data/lib/middleman-core/renderers/less.rb +3 -4
  42. data/lib/middleman-core/renderers/markdown.rb +2 -8
  43. data/lib/middleman-core/renderers/redcarpet.rb +1 -1
  44. data/lib/middleman-core/renderers/sass.rb +8 -11
  45. data/lib/middleman-core/renderers/stylus.rb +1 -5
  46. data/lib/middleman-core/sitemap/extensions/ignores.rb +5 -4
  47. data/lib/middleman-core/sitemap/extensions/import.rb +12 -15
  48. data/lib/middleman-core/sitemap/extensions/move_file.rb +3 -3
  49. data/lib/middleman-core/sitemap/extensions/proxies.rb +4 -4
  50. data/lib/middleman-core/sitemap/extensions/redirects.rb +16 -28
  51. data/lib/middleman-core/sitemap/extensions/request_endpoints.rb +17 -35
  52. data/lib/middleman-core/sitemap/extensions/traversal.rb +5 -5
  53. data/lib/middleman-core/sitemap/resource.rb +16 -16
  54. data/lib/middleman-core/sitemap/store.rb +42 -31
  55. data/lib/middleman-core/sources.rb +9 -9
  56. data/lib/middleman-core/sources/source_watcher.rb +14 -10
  57. data/lib/middleman-core/step_definitions/server_steps.rb +12 -4
  58. data/lib/middleman-core/template_context.rb +1 -1
  59. data/lib/middleman-core/template_renderer.rb +74 -75
  60. data/lib/middleman-core/util.rb +19 -16
  61. data/lib/middleman-core/util/data.rb +86 -82
  62. data/lib/middleman-core/version.rb +1 -1
  63. data/middleman-core.gemspec +1 -0
  64. metadata +19 -39
  65. data/features/cli/preview_server-hook.feature +0 -17
  66. data/features/cli/preview_server.feature +0 -536
  67. data/features/cli_extension.feature +0 -14
  68. data/features/cli_init.feature +0 -89
  69. data/fixtures/asset-hash-host-app/config.rb +0 -4
  70. data/fixtures/preview-server-app/bin/dns_server.rb +0 -33
  71. data/fixtures/preview-server-app/config.rb +0 -0
  72. data/fixtures/preview-server-app/source/index.html.erb +0 -1
  73. data/fixtures/preview-server-app/source/layout.erb +0 -9
  74. data/fixtures/preview-server-app/source/layouts/custom.erb +0 -8
  75. data/fixtures/preview-server-app/source/real.html +0 -1
  76. data/fixtures/preview-server-app/source/real/index.html.erb +0 -5
  77. data/fixtures/preview-server-app/source/should_be_ignored.html +0 -1
  78. data/fixtures/preview-server-app/source/should_be_ignored2.html +0 -1
  79. data/fixtures/preview-server-app/source/should_be_ignored3.html +0 -1
  80. data/fixtures/preview-server-app/source/static.html +0 -1
  81. data/fixtures/preview-server-hook-app/config.rb +0 -19
  82. data/fixtures/preview-server-hook-app/source/index.html.erb +0 -9
  83. data/lib/middleman-core/middleware/inline_url_rewriter.rb +0 -109
@@ -3,46 +3,48 @@ require 'active_support/core_ext/hash/deep_merge'
3
3
  require 'monitor'
4
4
  require 'hamster'
5
5
 
6
+ require 'middleman-core/extensions'
7
+
6
8
  # Files on Disk
7
- Middleman::Extensions.register :sitemap_ondisk, auto_activate: :before_configuration do
9
+ ::Middleman::Extensions.register :sitemap_ondisk, auto_activate: :before_configuration do
8
10
  require 'middleman-core/sitemap/extensions/on_disk'
9
- Middleman::Sitemap::Extensions::OnDisk
11
+ ::Middleman::Sitemap::Extensions::OnDisk
10
12
  end
11
13
 
12
14
  # Files on Disk (outside the project root)
13
- Middleman::Extensions.register :sitemap_import, auto_activate: :before_configuration do
15
+ ::Middleman::Extensions.register :sitemap_import, auto_activate: :before_configuration do
14
16
  require 'middleman-core/sitemap/extensions/import'
15
- Middleman::Sitemap::Extensions::Import
17
+ ::Middleman::Sitemap::Extensions::Import
16
18
  end
17
19
 
18
20
  # Endpoints
19
- Middleman::Extensions.register :sitemap_endpoint, auto_activate: :before_configuration do
21
+ ::Middleman::Extensions.register :sitemap_endpoint, auto_activate: :before_configuration do
20
22
  require 'middleman-core/sitemap/extensions/request_endpoints'
21
- Middleman::Sitemap::Extensions::RequestEndpoints
23
+ ::Middleman::Sitemap::Extensions::RequestEndpoints
22
24
  end
23
25
 
24
26
  # Proxies
25
- Middleman::Extensions.register :sitemap_proxies, auto_activate: :before_configuration do
27
+ ::Middleman::Extensions.register :sitemap_proxies, auto_activate: :before_configuration do
26
28
  require 'middleman-core/sitemap/extensions/proxies'
27
- Middleman::Sitemap::Extensions::Proxies
29
+ ::Middleman::Sitemap::Extensions::Proxies
28
30
  end
29
31
 
30
32
  # Redirects
31
- Middleman::Extensions.register :sitemap_redirects, auto_activate: :before_configuration do
33
+ ::Middleman::Extensions.register :sitemap_redirects, auto_activate: :before_configuration do
32
34
  require 'middleman-core/sitemap/extensions/redirects'
33
- Middleman::Sitemap::Extensions::Redirects
35
+ ::Middleman::Sitemap::Extensions::Redirects
34
36
  end
35
37
 
36
38
  # Move Files
37
- Middleman::Extensions.register :sitemap_move_files, auto_activate: :before_configuration do
39
+ ::Middleman::Extensions.register :sitemap_move_files, auto_activate: :before_configuration do
38
40
  require 'middleman-core/sitemap/extensions/move_file'
39
- Middleman::Sitemap::Extensions::MoveFile
41
+ ::Middleman::Sitemap::Extensions::MoveFile
40
42
  end
41
43
 
42
44
  # Ignores
43
- Middleman::Extensions.register :sitemap_ignore, auto_activate: :before_configuration do
45
+ ::Middleman::Extensions.register :sitemap_ignore, auto_activate: :before_configuration do
44
46
  require 'middleman-core/sitemap/extensions/ignores'
45
- Middleman::Sitemap::Extensions::Ignores
47
+ ::Middleman::Sitemap::Extensions::Ignores
46
48
  end
47
49
 
48
50
  require 'middleman-core/contracts'
@@ -73,6 +75,7 @@ module Middleman
73
75
  def initialize(app)
74
76
  @app = app
75
77
  @resources = []
78
+ @rebuild_reasons = [:first_run]
76
79
  @update_count = 0
77
80
 
78
81
  @resource_list_manipulators = ::Hamster::Vector.empty
@@ -113,9 +116,10 @@ module Middleman
113
116
 
114
117
  # Rebuild the list of resources from scratch, using registed manipulators
115
118
  # @return [void]
116
- Contract Maybe[Symbol] => Any
117
- def rebuild_resource_list!(name=nil)
119
+ Contract Symbol => Any
120
+ def rebuild_resource_list!(name)
118
121
  @lock.synchronize do
122
+ @rebuild_reasons << name
119
123
  @app.logger.debug "== Requesting resource list rebuilding: #{name}"
120
124
  @needs_sitemap_rebuild = true
121
125
  end
@@ -196,29 +200,36 @@ module Middleman
196
200
  def ensure_resource_list_updated!
197
201
  @lock.synchronize do
198
202
  return unless @needs_sitemap_rebuild
199
- @needs_sitemap_rebuild = false
200
203
 
201
- @app.logger.debug '== Rebuilding resource list'
204
+ ::Middleman::Util.instrument 'sitemap.update', reasons: @rebuild_reasons.uniq do
205
+ @needs_sitemap_rebuild = false
206
+
207
+ @app.logger.debug '== Rebuilding resource list'
208
+
209
+ @resources = []
202
210
 
203
- @resources = []
211
+ @resource_list_manipulators.each do |m|
212
+ ::Middleman::Util.instrument 'sitemap.manipulator', name: m[:name] do
213
+ @app.logger.debug "== Running manipulator: #{m[:name]}"
214
+ @resources = m[:manipulator].send(m[:custom_name] || :manipulate_resource_list, @resources)
204
215
 
205
- @resource_list_manipulators.each do |m|
206
- @app.logger.debug "== Running manipulator: #{m[:name]}"
207
- @resources = m[:manipulator].send(m[:custom_name] || :manipulate_resource_list, @resources)
216
+ # Reset lookup cache
217
+ reset_lookup_cache!
208
218
 
209
- # Reset lookup cache
210
- reset_lookup_cache!
219
+ # Rebuild cache
220
+ @resources.each do |resource|
221
+ @_lookup_by_path[resource.path] = resource
222
+ @_lookup_by_destination_path[resource.destination_path] = resource
223
+ end
211
224
 
212
- # Rebuild cache
213
- @resources.each do |resource|
214
- @_lookup_by_path[resource.path] = resource
215
- @_lookup_by_destination_path[resource.destination_path] = resource
225
+ invalidate_resources_not_ignored_cache!
226
+ end
216
227
  end
217
228
 
218
- invalidate_resources_not_ignored_cache!
219
- end
229
+ @update_count += 1
220
230
 
221
- @update_count += 1
231
+ @rebuild_reasons = []
232
+ end
222
233
  end
223
234
  end
224
235
 
@@ -15,10 +15,10 @@ module Middleman
15
15
  include Contracts
16
16
 
17
17
  # Types which could cause output to change.
18
- OUTPUT_TYPES = [:source, :locales, :data]
18
+ OUTPUT_TYPES = [:source, :locales, :data].freeze
19
19
 
20
20
  # Types which require a reload to eval ruby
21
- CODE_TYPES = [:reload]
21
+ CODE_TYPES = [:reload].freeze
22
22
 
23
23
  Matcher = Or[Regexp, RespondTo[:call]]
24
24
 
@@ -213,12 +213,12 @@ module Middleman
213
213
  # Manually poll all watchers for new content.
214
214
  #
215
215
  # @return [void]
216
- Contract Any
216
+ Contract ArrayOf[Pathname]
217
217
  def find_new_files!
218
- return unless @update_count != @last_update_count
218
+ return [] unless @update_count != @last_update_count
219
219
 
220
220
  @last_update_count = @update_count
221
- watchers.each(&:poll_once!)
221
+ watchers.reduce([]) { |sum, w| sum + w.poll_once! }
222
222
  end
223
223
 
224
224
  # Start up all listeners.
@@ -257,11 +257,11 @@ module Middleman
257
257
  #
258
258
  # @param [nil,Regexp] matcher A Regexp to match the change path against
259
259
  Contract Maybe[Matcher] => Any
260
- def changed(matcher=nil, &block)
260
+ def changed(matcher=nil, &_block)
261
261
  on_change OUTPUT_TYPES do |updated, _removed|
262
262
  updated
263
263
  .select { |f| matcher.nil? ? true : matches?(matcher, f) }
264
- .each { |f| block.call(f[:relative_path]) }
264
+ .each { |f| yield f[:relative_path] }
265
265
  end
266
266
  end
267
267
 
@@ -269,11 +269,11 @@ module Middleman
269
269
  #
270
270
  # @param [nil,Regexp] matcher A Regexp to match the change path against
271
271
  Contract Maybe[Matcher] => Any
272
- def deleted(matcher=nil, &block)
272
+ def deleted(matcher=nil, &_block)
273
273
  on_change OUTPUT_TYPES do |_updated, removed|
274
274
  removed
275
275
  .select { |f| matcher.nil? ? true : matches?(matcher, f) }
276
- .each { |f| block.call(f[:relative_path]) }
276
+ .each { |f| yield f[:relative_path] }
277
277
  end
278
278
  end
279
279
 
@@ -91,7 +91,7 @@ module Middleman
91
91
 
92
92
  stop_listener! if @listener
93
93
 
94
- update([], @files.values)
94
+ update([], @files.values.map { |source_file| source_file[:full_path] })
95
95
 
96
96
  poll_once!
97
97
 
@@ -180,17 +180,19 @@ module Middleman
180
180
  # Manually trigger update events.
181
181
  #
182
182
  # @return [void]
183
- Contract Any
183
+ Contract ArrayOf[Pathname]
184
184
  def poll_once!
185
185
  updated = ::Middleman::Util.all_files_under(@directory.to_s)
186
186
  removed = @files.keys.reject { |p| updated.include?(p) }
187
187
 
188
188
  update(updated, removed)
189
189
 
190
- return unless @waiting_for_existence && @directory.exist?
190
+ if @waiting_for_existence && @directory.exist?
191
+ @waiting_for_existence = false
192
+ listen!
193
+ end
191
194
 
192
- @waiting_for_existence = false
193
- listen!
195
+ updated + removed
194
196
  end
195
197
 
196
198
  # Work around this bug: http://bugs.ruby-lang.org/issues/4521
@@ -200,7 +202,7 @@ module Middleman
200
202
  def to_s
201
203
  "#<Middleman::SourceWatcher:0x#{object_id} type=#{@type.inspect} directory=#{@directory.inspect}>"
202
204
  end
203
- alias_method :inspect, :to_s # Ruby 2.0 calls inspect for NoMethodError instead of to_s
205
+ alias inspect to_s # Ruby 2.0 calls inspect for NoMethodError instead of to_s
204
206
 
205
207
  protected
206
208
 
@@ -254,17 +256,19 @@ module Middleman
254
256
  end
255
257
 
256
258
  execute_callbacks(:on_change, [
257
- valid_updates,
258
- valid_removes,
259
- self
260
- ]) unless valid_updates.empty? && valid_removes.empty?
259
+ valid_updates,
260
+ valid_removes,
261
+ self
262
+ ]) unless valid_updates.empty? && valid_removes.empty?
261
263
  end
262
264
 
265
+ Contract IsA['Middleman::SourceFile'] => Any
263
266
  def add_file_to_cache(f)
264
267
  @files[f[:full_path]] = f
265
268
  @extensionless_files[strip_extensions(f[:full_path])] = f
266
269
  end
267
270
 
271
+ Contract IsA['Middleman::SourceFile'] => Any
268
272
  def remove_file_from_cache(f)
269
273
  @files.delete(f[:full_path])
270
274
  @extensionless_files.delete(strip_extensions(f[:full_path]))
@@ -4,22 +4,23 @@ require 'capybara/cucumber'
4
4
 
5
5
  Given /^a clean server$/ do
6
6
  @initialize_commands = []
7
+ @activation_commands = []
7
8
  end
8
9
 
9
10
  Given /^"([^\"]*)" feature is "([^\"]*)"$/ do |feature, state|
10
- @initialize_commands ||= []
11
+ @activation_commands ||= []
11
12
 
12
13
  if state == 'enabled'
13
- @initialize_commands << lambda { activate(feature.to_sym) }
14
+ @activation_commands << lambda { activate(feature.to_sym) }
14
15
  end
15
16
  end
16
17
 
17
18
  Given /^"([^\"]*)" feature is "enabled" with "([^\"]*)"$/ do |feature, options_str|
18
- @initialize_commands ||= []
19
+ @activation_commands ||= []
19
20
 
20
21
  options = eval("{#{options_str}}")
21
22
 
22
- @initialize_commands << lambda { activate(feature.to_sym, options) }
23
+ @activation_commands << lambda { activate(feature.to_sym, options) }
23
24
  end
24
25
 
25
26
  Given /^"([^\"]*)" is set to "([^\"]*)"$/ do |variable, value|
@@ -41,6 +42,7 @@ Given /^the Server is running$/ do
41
42
  ENV['MM_ROOT'] = root_dir
42
43
 
43
44
  initialize_commands = @initialize_commands || []
45
+ activation_commands = @activation_commands || []
44
46
 
45
47
  @server_inst = ::Middleman::Application.new do
46
48
  config[:watcher_disable] = true
@@ -49,6 +51,12 @@ Given /^the Server is running$/ do
49
51
  initialize_commands.each do |p|
50
52
  instance_exec(&p)
51
53
  end
54
+
55
+ app.after_configuration_eval do
56
+ activation_commands.each do |p|
57
+ config_context.instance_exec(&p)
58
+ end
59
+ end
52
60
  end
53
61
 
54
62
  Capybara.app = ::Middleman::Rack.new(@server_inst).to_app
@@ -162,7 +162,7 @@ module Middleman
162
162
  return nil unless current_path
163
163
  sitemap.find_resource_by_destination_path(current_path)
164
164
  end
165
- alias_method :current_page, :current_resource
165
+ alias current_page current_resource
166
166
 
167
167
  protected
168
168
 
@@ -28,6 +28,75 @@ module Middleman
28
28
  @_cache ||= Cache.new
29
29
  end
30
30
 
31
+ # Find a layout on-disk, optionally using a specific engine
32
+ # @param [String] name
33
+ # @param [Symbol] preferred_engine
34
+ # @return [String]
35
+ Contract IsA['Middleman::Application'], Or[String, Symbol], Symbol => Maybe[IsA['Middleman::SourceFile']]
36
+ def self.locate_layout(app, name, preferred_engine=nil)
37
+ resolve_opts = {}
38
+ resolve_opts[:preferred_engine] = preferred_engine unless preferred_engine.nil?
39
+
40
+ # Check layouts folder
41
+ layout_file = resolve_template(app, File.join(app.config[:layouts_dir], name.to_s), resolve_opts)
42
+
43
+ # If we didn't find it, check root
44
+ layout_file = resolve_template(app, name, resolve_opts) unless layout_file
45
+
46
+ # Return the path
47
+ layout_file
48
+ end
49
+
50
+ # Find a template on disk given a output path
51
+ # @param [String] request_path
52
+ # @option options [Boolean] :preferred_engine If set, try this engine first, then fall back to any engine.
53
+ # @return [String, Boolean] Either the path to the template, or false
54
+ Contract IsA['Middleman::Application'], Or[Symbol, String], Maybe[Hash] => Maybe[IsA['Middleman::SourceFile']]
55
+ def self.resolve_template(app, request_path, options={})
56
+ # Find the path by searching
57
+ relative_path = Util.strip_leading_slash(request_path.to_s)
58
+
59
+ # By default, any engine will do
60
+ preferred_engines = []
61
+
62
+ # If we're specifically looking for a preferred engine
63
+ if options.key?(:preferred_engine)
64
+ extension_class = ::Tilt[options[:preferred_engine]]
65
+
66
+ # Get a list of extensions for a preferred engine
67
+ preferred_engines += ::Tilt.mappings.select do |_, engines|
68
+ engines.include? extension_class
69
+ end.keys
70
+ end
71
+
72
+ preferred_engines << '*'
73
+ preferred_engines << nil if options[:try_static]
74
+
75
+ found_template = nil
76
+
77
+ preferred_engines.each do |preferred_engine|
78
+ path_with_ext = relative_path.dup
79
+ path_with_ext << ('.' + preferred_engine) unless preferred_engine.nil?
80
+
81
+ globbing = preferred_engine == '*'
82
+
83
+ # Cache lookups in build mode only
84
+ file = if app.build?
85
+ cache.fetch(path_with_ext, preferred_engine) do
86
+ app.files.find(:source, path_with_ext, globbing)
87
+ end
88
+ else
89
+ app.files.find(:source, path_with_ext, globbing)
90
+ end
91
+
92
+ found_template = file if file && (preferred_engine.nil? || ::Tilt[file[:full_path]])
93
+ break if found_template
94
+ end
95
+
96
+ # If we found one, return it
97
+ found_template
98
+ end
99
+
31
100
  # Custom error class for handling
32
101
  class TemplateNotFound < RuntimeError; end
33
102
 
@@ -132,14 +201,13 @@ module Middleman
132
201
  # Look for :layout of any extension
133
202
  # If found, use it. If not, continue
134
203
  locate_layout(:layout, layout_engine)
135
- else
204
+ elsif layout_file = locate_layout(local_layout, layout_engine)
136
205
  # Look for specific layout
137
206
  # If found, use it. If not, error.
138
- if layout_file = locate_layout(local_layout, layout_engine)
139
- layout_file
140
- else
141
- raise ::Middleman::TemplateRenderer::TemplateNotFound, "Could not locate layout: #{local_layout}"
142
- end
207
+
208
+ layout_file
209
+ else
210
+ raise ::Middleman::TemplateRenderer::TemplateNotFound, "Could not locate layout: #{local_layout}"
143
211
  end
144
212
  end
145
213
 
@@ -152,25 +220,6 @@ module Middleman
152
220
  self.class.locate_layout(@app, name, preferred_engine)
153
221
  end
154
222
 
155
- # Find a layout on-disk, optionally using a specific engine
156
- # @param [String] name
157
- # @param [Symbol] preferred_engine
158
- # @return [String]
159
- Contract IsA['Middleman::Application'], Or[String, Symbol], Symbol => Maybe[IsA['Middleman::SourceFile']]
160
- def self.locate_layout(app, name, preferred_engine=nil)
161
- resolve_opts = {}
162
- resolve_opts[:preferred_engine] = preferred_engine unless preferred_engine.nil?
163
-
164
- # Check layouts folder
165
- layout_file = resolve_template(app, File.join(app.config[:layouts_dir], name.to_s), resolve_opts)
166
-
167
- # If we didn't find it, check root
168
- layout_file = resolve_template(app, name, resolve_opts) unless layout_file
169
-
170
- # Return the path
171
- layout_file
172
- end
173
-
174
223
  # Find a template on disk given a output path
175
224
  # @param [String] request_path
176
225
  # @param [Hash] options
@@ -179,55 +228,5 @@ module Middleman
179
228
  def resolve_template(request_path, options={})
180
229
  self.class.resolve_template(@app, request_path, options)
181
230
  end
182
-
183
- # Find a template on disk given a output path
184
- # @param [String] request_path
185
- # @option options [Boolean] :preferred_engine If set, try this engine first, then fall back to any engine.
186
- # @return [String, Boolean] Either the path to the template, or false
187
- Contract IsA['Middleman::Application'], Or[Symbol, String], Maybe[Hash] => Maybe[IsA['Middleman::SourceFile']]
188
- def self.resolve_template(app, request_path, options={})
189
- # Find the path by searching
190
- relative_path = Util.strip_leading_slash(request_path.to_s)
191
-
192
- # By default, any engine will do
193
- preferred_engines = []
194
-
195
- # If we're specifically looking for a preferred engine
196
- if options.key?(:preferred_engine)
197
- extension_class = ::Tilt[options[:preferred_engine]]
198
-
199
- # Get a list of extensions for a preferred engine
200
- preferred_engines += ::Tilt.mappings.select do |_, engines|
201
- engines.include? extension_class
202
- end.keys
203
- end
204
-
205
- preferred_engines << '*'
206
- preferred_engines << nil if options[:try_static]
207
-
208
- found_template = nil
209
-
210
- preferred_engines.each do |preferred_engine|
211
- path_with_ext = relative_path.dup
212
- path_with_ext << ('.' + preferred_engine) unless preferred_engine.nil?
213
-
214
- globbing = preferred_engine == '*'
215
-
216
- # Cache lookups in build mode only
217
- file = if app.build?
218
- cache.fetch(path_with_ext, preferred_engine) do
219
- app.files.find(:source, path_with_ext, globbing)
220
- end
221
- else
222
- app.files.find(:source, path_with_ext, globbing)
223
- end
224
-
225
- found_template = file if file && (preferred_engine.nil? || ::Tilt[file[:full_path]])
226
- break if found_template
227
- end
228
-
229
- # If we found one, return it
230
- found_template
231
- end
232
231
  end
233
232
  end