middleman-core 4.1.7 → 4.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/features/collections.feature +27 -0
  3. data/features/i18n_link_to.feature +34 -34
  4. data/features/relative_assets.feature +1 -1
  5. data/features/relative_assets_helpers_only.feature +123 -0
  6. data/features/template-key-collision.feature +26 -0
  7. data/fixtures/relative-assets-app/source/images/blank2.gif +0 -0
  8. data/lib/middleman-core/config_context.rb +2 -2
  9. data/lib/middleman-core/core_extensions/collections/step_context.rb +8 -5
  10. data/lib/middleman-core/core_extensions/collections.rb +1 -1
  11. data/lib/middleman-core/core_extensions/default_helpers.rb +1 -0
  12. data/lib/middleman-core/core_extensions/front_matter.rb +8 -6
  13. data/lib/middleman-core/core_extensions/inline_url_rewriter.rb +20 -35
  14. data/lib/middleman-core/extension.rb +4 -1
  15. data/lib/middleman-core/extensions/asset_hash.rb +1 -1
  16. data/lib/middleman-core/extensions/asset_host.rb +2 -1
  17. data/lib/middleman-core/extensions/minify_css.rb +9 -1
  18. data/lib/middleman-core/extensions/minify_javascript.rb +8 -0
  19. data/lib/middleman-core/extensions/relative_assets.rb +39 -12
  20. data/lib/middleman-core/file_renderer.rb +4 -4
  21. data/lib/middleman-core/sitemap/resource.rb +3 -3
  22. data/lib/middleman-core/sitemap/store.rb +1 -1
  23. data/lib/middleman-core/sources/source_watcher.rb +6 -0
  24. data/lib/middleman-core/template_context.rb +3 -2
  25. data/lib/middleman-core/template_renderer.rb +22 -9
  26. data/lib/middleman-core/util/data.rb +32 -17
  27. data/lib/middleman-core/util/files.rb +3 -7
  28. data/lib/middleman-core/util/paths.rb +38 -0
  29. data/lib/middleman-core/util/rack.rb +1 -1
  30. data/lib/middleman-core/version.rb +1 -1
  31. data/middleman-core.gemspec +3 -2
  32. data/spec/middleman-core/util_spec.rb +16 -0
  33. metadata +25 -5
@@ -1,4 +1,6 @@
1
+ require 'active_support/core_ext/object/try'
1
2
  require 'middleman-core/contracts'
3
+ require 'memoist'
2
4
 
3
5
  # Minify Javascript Extension
4
6
  class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
@@ -22,6 +24,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
22
24
 
23
25
  # Rack middleware to look for JS and compress it
24
26
  class Rack
27
+ extend Memoist
25
28
  include Contracts
26
29
  INLINE_JS_REGEX = /(<script[^>]*>\s*(?:\/\/(?:(?:<!--)|(?:<!\[CDATA\[))\n)?)(.*?)((?:(?:\n\s*)?\/\/(?:(?:-->)|(?:\]\]>)))?\s*<\/script>)/m
27
30
 
@@ -76,6 +79,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
76
79
  def ignore?(path)
77
80
  @ignore.any? { |ignore| Middleman::Util.path_match(ignore, path) }
78
81
  end
82
+ memoize :ignore?
79
83
 
80
84
  # Whether this type of content can be minified
81
85
  # @param [String, nil] content_type
@@ -83,6 +87,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
83
87
  def minifiable?(content_type)
84
88
  @content_types.include?(content_type)
85
89
  end
90
+ memoize :minifiable?
86
91
 
87
92
  # Whether this type of content contains inline content that can be minified
88
93
  # @param [String, nil] content_type
@@ -90,6 +95,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
90
95
  def minifiable_inline?(content_type)
91
96
  @inline_content_types.include?(content_type)
92
97
  end
98
+ memoize :minifiable_inline?
93
99
 
94
100
  # Minify the content
95
101
  # @param [String] content
@@ -100,6 +106,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
100
106
  warn "WARNING: Couldn't compress JavaScript in #{@path}: #{e.message}"
101
107
  content
102
108
  end
109
+ memoize :minify
103
110
 
104
111
  # Detect and minify inline content
105
112
  # @param [String] content
@@ -119,5 +126,6 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
119
126
  end
120
127
  end
121
128
  end
129
+ memoize :minify_inline
122
130
  end
123
131
  end
@@ -2,15 +2,20 @@ require 'addressable/uri'
2
2
 
3
3
  # Relative Assets extension
4
4
  class Middleman::Extensions::RelativeAssets < ::Middleman::Extension
5
- option :exts, nil, 'List of extensions that get cache busters strings appended to them.'
5
+ option :exts, nil, 'List of extensions that get converted to relative paths.'
6
6
  option :sources, %w(.css .htm .html .xhtml), 'List of extensions that are searched for relative assets.'
7
- option :ignore, [], 'Regexes of filenames to skip adding query strings to'
8
- option :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites'
7
+ option :ignore, [], 'Regexes of filenames to skip converting to relative paths.'
8
+ option :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites.'
9
+ option :helpers_only, false, 'Allow only Ruby helpers to change paths.'
9
10
 
10
11
  def initialize(app, options_hash={}, &block)
11
12
  super
12
13
 
13
- app.rewrite_inline_urls id: :asset_hash,
14
+ if options[:helpers_only]
15
+ return
16
+ end
17
+
18
+ app.rewrite_inline_urls id: :relative_assets,
14
19
  url_extensions: options.exts || app.config[:asset_extensions],
15
20
  source_extensions: options.sources,
16
21
  ignore: options.ignore,
@@ -18,22 +23,43 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension
18
23
  proc: method(:rewrite_url)
19
24
  end
20
25
 
26
+ def mark_as_relative(file_path, opts, current_resource)
27
+ result = opts.dup
28
+
29
+ valid_exts = options.sources
30
+
31
+ return result unless current_resource
32
+ return result unless valid_exts.include?(current_resource.ext)
33
+
34
+ rewrite_ignores = Array(options.rewrite_ignore || [])
35
+
36
+ path = current_resource.destination_path
37
+ return result if rewrite_ignores.any? do |i|
38
+ ::Middleman::Util.path_match(i, path) || ::Middleman::Util.path_match(i, "/#{path}")
39
+ end
40
+
41
+ return result if Array(options.ignore || []).any? do |r|
42
+ ::Middleman::Util.should_ignore?(r, file_path)
43
+ end
44
+
45
+ result[:relative] = true unless result.key?(:relative)
46
+
47
+ result
48
+ end
49
+
21
50
  helpers do
22
- # asset_url override for relative assets
23
- # @param [String] path
24
- # @param [String] prefix
25
- # @param [Hash] options Additional options.
26
- # @return [String]
27
51
  def asset_url(path, prefix='', options={})
28
- options[:relative] = true unless options.key?(:relative)
52
+ super(path, prefix, app.extensions[:relative_assets].mark_as_relative(super, options, current_resource))
53
+ end
29
54
 
30
- super(path, prefix, options)
55
+ def asset_path(kind, source, options={})
56
+ super(kind, source, app.extensions[:relative_assets].mark_as_relative(super, options, current_resource))
31
57
  end
32
58
  end
33
59
 
34
60
  Contract String, Or[String, Pathname], Any => Maybe[String]
35
61
  def rewrite_url(asset_path, dirpath, request_path)
36
- uri = ::Addressable::URI.parse(asset_path)
62
+ uri = ::Middleman::Util.parse_uri(asset_path)
37
63
 
38
64
  return if uri.path[0..0] != '/'
39
65
 
@@ -50,4 +76,5 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension
50
76
 
51
77
  result
52
78
  end
79
+ memoize :rewrite_url
53
80
  end
@@ -59,7 +59,7 @@ module Middleman
59
59
  # Overwrite with frontmatter options
60
60
  options = options.deep_merge(options[:renderer_options]) if options[:renderer_options]
61
61
 
62
- template_class = ::Tilt[path]
62
+ template_class = ::Middleman::Util.tilt_class(path)
63
63
 
64
64
  # Allow hooks to manipulate the template before render
65
65
  body = @app.callbacks_for(:before_render).reduce(body) do |sum, callback|
@@ -99,12 +99,12 @@ module Middleman
99
99
  def template_data_for_file
100
100
  file = @app.files.find(:source, @path)
101
101
 
102
- if @app.extensions[:front_matter] || (file && !file[:types].include?(:no_frontmatter))
102
+ if @app.extensions[:front_matter] && (file && !file[:types].include?(:no_frontmatter))
103
103
  result = @app.extensions[:front_matter].template_data_for_file(@path)
104
104
  return result unless result.nil?
105
105
  end
106
106
 
107
- file ? file.read : File.read(@path)
107
+ file ? file.read : ::File.read(@path)
108
108
  end
109
109
 
110
110
  protected
@@ -122,7 +122,7 @@ module Middleman
122
122
 
123
123
  # Find all the engines which handle this extension in tilt. Look for
124
124
  # config variables of that name and merge it
125
- extension_class = ::Tilt[ext]
125
+ extension_class = ::Middleman::Util.tilt_class(ext)
126
126
  ::Tilt.mappings.each do |mapping_ext, engines|
127
127
  next unless engines.include? extension_class
128
128
  engine_options = @app.config[mapping_ext.to_sym] || {}
@@ -75,17 +75,17 @@ module Middleman
75
75
  Contract Bool
76
76
  def template?
77
77
  return false if file_descriptor.nil?
78
- !::Tilt[file_descriptor[:full_path].to_s].nil?
78
+ !::Middleman::Util.tilt_class(file_descriptor[:full_path].to_s).nil?
79
79
  end
80
80
 
81
81
  # Backwards compatible method for turning descriptor into a string.
82
82
  # @return [String]
83
- Contract String
83
+ Contract Maybe[String]
84
84
  def source_file
85
85
  file_descriptor && file_descriptor[:full_path].to_s
86
86
  end
87
87
 
88
- Contract Or[Symbol, String]
88
+ Contract Or[Symbol, String, Fixnum]
89
89
  def page_id
90
90
  metadata[:page][:id] || destination_path
91
91
  end
@@ -102,7 +102,7 @@ module Middleman
102
102
  # @param [Numeric] priority Sets the order of this resource list manipulator relative to the rest. By default this is 50, and manipulators run in the order they are registered, but if a priority is provided then this will run ahead of or behind other manipulators.
103
103
  # @param [Symbol] custom_name The method name to execute.
104
104
  # @return [void]
105
- Contract Symbol, RespondTo[:manipulate_resource_list], Maybe[Num], Maybe[Symbol] => Any
105
+ Contract Symbol, RespondTo[:manipulate_resource_list], Maybe[Num, Bool], Maybe[Symbol] => Any
106
106
  def register_resource_list_manipulator(name, manipulator, priority=50, custom_name=nil)
107
107
  # The third argument used to be a boolean - handle those who still pass one
108
108
  priority = 50 unless priority.is_a? Numeric
@@ -298,9 +298,15 @@ module Middleman
298
298
  relative_path = path.relative_path_from(directory)
299
299
  relative_path = File.join(destination_dir, relative_path) if destination_dir
300
300
 
301
+ types << :no_frontmatter if partial?(relative_path.to_s)
302
+
301
303
  ::Middleman::SourceFile.new(Pathname(relative_path), path, directory, types, 0)
302
304
  end
303
305
 
306
+ def partial?(relative_path)
307
+ relative_path.split(::File::SEPARATOR).any? { |p| p.start_with?('_') }
308
+ end
309
+
304
310
  Contract IsA['Middleman::SourceFile'] => Any
305
311
  def record_file_change(f)
306
312
  if @files[f[:full_path]]
@@ -23,7 +23,7 @@ module Middleman
23
23
  attr_accessor :current_engine
24
24
 
25
25
  # Shorthand references to global values on the app instance.
26
- def_delegators :@app, :config, :logger, :sitemap, :server?, :build?, :environment?, :environment, :data, :extensions, :root
26
+ def_delegators :@app, :config, :logger, :sitemap, :server?, :build?, :environment?, :environment, :data, :extensions, :root, :development?, :production?
27
27
 
28
28
  # Initialize a context with the current app and predefined locals and options hashes.
29
29
  #
@@ -84,6 +84,7 @@ module Middleman
84
84
  # Reset stored buffer, regardless of success
85
85
  restore_buffer(buf_was)
86
86
  end
87
+
87
88
  # Render the layout, with the contents of the block inside.
88
89
  concat_safe_content render_file(layout_file, @locs, @opts) { content }
89
90
  ensure
@@ -185,7 +186,7 @@ module Middleman
185
186
  # handles cases like `style.css.sass.erb`
186
187
  content = nil
187
188
 
188
- while ::Tilt[path]
189
+ while ::Middleman::Util.tilt_class(path)
189
190
  begin
190
191
  opts[:template_body] = content if content
191
192
 
@@ -61,7 +61,7 @@ module Middleman
61
61
 
62
62
  # If we're specifically looking for a preferred engine
63
63
  if options.key?(:preferred_engine)
64
- extension_class = ::Tilt[options[:preferred_engine]]
64
+ extension_class = ::Middleman::Util.tilt_class(options[:preferred_engine])
65
65
 
66
66
  # Get a list of extensions for a preferred engine
67
67
  preferred_engines += ::Tilt.mappings.select do |_, engines|
@@ -89,7 +89,7 @@ module Middleman
89
89
  app.files.find(:source, path_with_ext, globbing)
90
90
  end
91
91
 
92
- found_template = file if file && (preferred_engine.nil? || ::Tilt[file[:full_path]])
92
+ found_template = file if file && (preferred_engine.nil? || ::Middleman::Util.tilt_class(file[:full_path].to_s))
93
93
  break if found_template
94
94
  end
95
95
 
@@ -133,20 +133,33 @@ module Middleman
133
133
  # Add extension helpers to context.
134
134
  @app.extensions.add_exposed_to_context(context)
135
135
 
136
+ locals.each do |k, _|
137
+ next unless context.respond_to?(k) && ![:current_path, :paginate, :page_articles, :blog_controller, :lang, :locale].include?(k.to_sym)
138
+
139
+ msg = "Template local `#{k}` tried to overwrite an existing context value. Please rename the key when passing to `locals`"
140
+
141
+ if @app.build?
142
+ throw msg
143
+ else
144
+ @app.logger.error(msg)
145
+ end
146
+ end
147
+
136
148
  content = ::Middleman::Util.instrument 'builder.output.resource.render-template', path: File.basename(path) do
137
- _render_with_all_renderers(path, locs, context, opts, &block)
149
+ _render_with_all_renderers(path, locals, context, options, &block)
138
150
  end
139
151
 
140
152
  # If we need a layout and have a layout, use it
141
153
  layout_file = fetch_layout(engine, options)
142
154
  if layout_file
143
- content = ::Middleman::Util.instrument 'builder.output.resource.render-layout', path: File.basename(layout_file[:relative_path].to_s) do
144
- if layout_file = fetch_layout(engine, options)
145
- layout_renderer = ::Middleman::FileRenderer.new(@app, layout_file[:relative_path].to_s)
155
+ content = if layout_file = fetch_layout(engine, options)
156
+ layout_renderer = ::Middleman::FileRenderer.new(@app, layout_file[:relative_path].to_s)
157
+
158
+ ::Middleman::Util.instrument 'builder.output.resource.render-layout', path: File.basename(layout_file[:relative_path].to_s) do
146
159
  layout_renderer.render(locals, options, context) { content }
147
- else
148
- content
149
160
  end
161
+ else
162
+ content
150
163
  end
151
164
  end
152
165
 
@@ -165,7 +178,7 @@ module Middleman
165
178
  # handles cases like `style.css.sass.erb`
166
179
  content = nil
167
180
 
168
- while ::Tilt[path]
181
+ while ::Middleman::Util.tilt_class(path)
169
182
  begin
170
183
  opts[:template_body] = content if content
171
184
 
@@ -3,6 +3,7 @@ require 'json'
3
3
  require 'pathname'
4
4
  require 'backports/2.1.0/array/to_h'
5
5
  require 'hashie'
6
+ require 'memoist'
6
7
 
7
8
  require 'middleman-core/util/binary'
8
9
  require 'middleman-core/contracts'
@@ -36,6 +37,7 @@ module Middleman
36
37
  end
37
38
 
38
39
  module Data
40
+ extend Memoist
39
41
  include Contracts
40
42
 
41
43
  module_function
@@ -55,20 +57,7 @@ module Middleman
55
57
  return [{}, nil]
56
58
  end
57
59
 
58
- start_delims, stop_delims = frontmatter_delims
59
- .values
60
- .flatten(1)
61
- .transpose
62
- .map(&::Regexp.method(:union))
63
-
64
- match = /
65
- \A(?:[^\r\n]*coding:[^\r\n]*\r?\n)?
66
- (?<start>#{start_delims})[ ]*\r?\n
67
- (?<frontmatter>.*?)[ ]*\r?\n?
68
- ^(?<stop>#{stop_delims})[ ]*\r?\n?
69
- \r?\n?
70
- (?<additional_content>.*)
71
- /mx.match(content) || {}
60
+ match = build_regex(frontmatter_delims).match(content) || {}
72
61
 
73
62
  unless match[:frontmatter]
74
63
  case known_type
@@ -98,27 +87,53 @@ module Middleman
98
87
  end
99
88
  end
100
89
 
90
+ def build_regex(frontmatter_delims)
91
+ start_delims, stop_delims = frontmatter_delims
92
+ .values
93
+ .flatten(1)
94
+ .transpose
95
+ .map(&::Regexp.method(:union))
96
+
97
+ match = /
98
+ \A(?:[^\r\n]*coding:[^\r\n]*\r?\n)?
99
+ (?<start>#{start_delims})[ ]*\r?\n
100
+ (?<frontmatter>.*?)[ ]*\r?\n?
101
+ ^(?<stop>#{stop_delims})[ ]*\r?\n?
102
+ \r?\n?
103
+ (?<additional_content>.*)
104
+ /mx
105
+ end
106
+ memoize :build_regex
107
+
101
108
  # Parse YAML frontmatter out of a string
102
109
  # @param [String] content
103
110
  # @return [Hash]
104
- Contract String, Pathname, Bool => Hash
111
+ Contract String, Pathname => Hash
105
112
  def parse_yaml(content, full_path)
106
- symbolize_recursive(::YAML.load(content) || {})
113
+ c = ::Middleman::Util.instrument 'parse.yaml' do
114
+ ::YAML.load(content)
115
+ end
116
+ c ? symbolize_recursive(c) : {}
107
117
  rescue StandardError, ::Psych::SyntaxError => error
108
118
  warn "YAML Exception parsing #{full_path}: #{error.message}"
109
119
  {}
110
120
  end
121
+ memoize :parse_yaml
111
122
 
112
123
  # Parse JSON frontmatter out of a string
113
124
  # @param [String] content
114
125
  # @return [Hash]
115
126
  Contract String, Pathname => Hash
116
127
  def parse_json(content, full_path)
117
- symbolize_recursive(::JSON.parse(content) || {})
128
+ c = ::Middleman::Util.instrument 'parse.json' do
129
+ ::JSON.parse(content)
130
+ end
131
+ c ? symbolize_recursive(c) : {}
118
132
  rescue StandardError => error
119
133
  warn "JSON Exception parsing #{full_path}: #{error.message}"
120
134
  {}
121
135
  end
136
+ memoize :parse_json
122
137
 
123
138
  def symbolize_recursive(value)
124
139
  case value
@@ -54,16 +54,12 @@ module Middleman
54
54
  result.encode('UTF-8', 'UTF-8-MAC')
55
55
  end
56
56
 
57
- Contract String => Bool
58
- def tilt_recognizes?(path)
59
- @@tilt_lookup_cache ||= {}
60
- @@tilt_lookup_cache[path] ||= ::Tilt[path]
61
- end
62
-
63
57
  Contract String => String
64
58
  def step_through_extensions(path)
65
- while tilt_recognizes?(path)
59
+ while ::Middleman::Util.tilt_class(path)
66
60
  ext = ::File.extname(path)
61
+ break if ext.empty?
62
+
67
63
  yield ext if block_given?
68
64
 
69
65
  # Strip templating extensions as long as Tilt knows them
@@ -1,16 +1,32 @@
1
1
  # Core Pathname library used for traversal
2
2
  require 'pathname'
3
3
  require 'uri'
4
+ require 'memoist'
5
+ require 'addressable'
6
+ require 'tilt'
4
7
 
5
8
  require 'middleman-core/contracts'
6
9
 
7
10
  # rubocop:disable ModuleLength
8
11
  module Middleman
9
12
  module Util
13
+ extend Memoist
10
14
  include Contracts
11
15
 
12
16
  module_function
13
17
 
18
+ Contract String => ::Addressable::URI
19
+ def parse_uri(uri)
20
+ ::Addressable::URI.parse(uri)
21
+ end
22
+ memoize :parse_uri
23
+
24
+ Contract String => Any
25
+ def tilt_class(path)
26
+ ::Tilt[path]
27
+ end
28
+ memoize :tilt_class
29
+
14
30
  # Normalize a path to not include a leading slash
15
31
  # @param [String] path
16
32
  # @return [String]
@@ -19,6 +35,7 @@ module Middleman
19
35
  # The tr call works around a bug in Ruby's Unicode handling
20
36
  ::URI.decode(path).sub(%r{^/}, '').tr('', '')
21
37
  end
38
+ memoize :normalize_path
22
39
 
23
40
  # This is a separate method from normalize_path in case we
24
41
  # change how we normalize paths
@@ -26,6 +43,26 @@ module Middleman
26
43
  def strip_leading_slash(path)
27
44
  path.sub(%r{^/}, '')
28
45
  end
46
+ memoize :strip_leading_slash
47
+
48
+ IGNORE_DESCRIPTOR = Or[Regexp, RespondTo[:call], String]
49
+ Contract IGNORE_DESCRIPTOR, String => Bool
50
+ def should_ignore?(validator, value)
51
+ if validator.is_a? Regexp
52
+ # Treat as Regexp
53
+ !!(value =~ validator)
54
+ elsif validator.respond_to? :call
55
+ # Treat as proc
56
+ validator.call(value)
57
+ elsif validator.is_a? String
58
+ # Treat as glob
59
+ File.fnmatch(value, validator)
60
+ else
61
+ # If some unknown thing, don't ignore
62
+ false
63
+ end
64
+ end
65
+ memoize :should_ignore?
29
66
 
30
67
  # Get the path of a file of a given type
31
68
  #
@@ -256,5 +293,6 @@ module Middleman
256
293
  ::File.fnmatch(matcher.to_s, path)
257
294
  end
258
295
  end
296
+ memoize :path_match
259
297
  end
260
298
  end
@@ -38,7 +38,7 @@ module Middleman
38
38
  current_resource = app.sitemap.find_resource_by_destination_path(path)
39
39
 
40
40
  begin
41
- uri = ::Addressable::URI.parse(asset_path)
41
+ uri = ::Middleman::Util.parse_uri(asset_path)
42
42
 
43
43
  if uri.relative? && uri.host.nil? && !(asset_path =~ /^[^\/].*[a-z]+\.[a-z]+\/.*/)
44
44
  dest_path = ::Middleman::Util.url_for(app, asset_path, relative: false, current_resource: current_resource)
@@ -1,5 +1,5 @@
1
1
  module Middleman
2
2
  # Current Version
3
3
  # @return [String]
4
- VERSION = '4.1.7'.freeze unless const_defined?(:VERSION)
4
+ VERSION = '4.1.8'.freeze unless const_defined?(:VERSION)
5
5
  end
@@ -31,12 +31,13 @@ Gem::Specification.new do |s|
31
31
  s.add_dependency('activesupport', ['~> 4.2'])
32
32
  s.add_dependency('padrino-helpers', ['~> 0.13.0'])
33
33
  s.add_dependency("addressable", ["~> 2.3"])
34
+ s.add_dependency('memoist', ['~> 0.14'])
34
35
 
35
36
  # Watcher
36
- s.add_dependency('listen', ['~> 3.0'])
37
+ s.add_dependency('listen', ['~> 3.0.0'])
37
38
 
38
39
  # Tests
39
- s.add_dependency("capybara", ["~> 2.5.0"])
40
+ s.add_development_dependency("capybara", ["~> 2.5.0"])
40
41
 
41
42
  # i18n
42
43
  s.add_dependency('i18n', ['~> 0.7.0'])
@@ -204,4 +204,20 @@ describe Middleman::Util do
204
204
  expect(related).to include File.expand_path("source/stylesheets/include2.css.scss")
205
205
  end
206
206
  end
207
+
208
+ describe "::step_through_extensions" do
209
+ it "returns the base name after templating engine extensions are removed" do
210
+ result = Middleman::Util.step_through_extensions('my_file.html.haml.erb')
211
+ expect(result).to eq 'my_file.html'
212
+ end
213
+
214
+ it "does not loop infinitely when file name is a possible templating engine" do
215
+ expect do
216
+ Timeout::timeout(0.5) do
217
+ result = Middleman::Util.step_through_extensions("markdown.scss")
218
+ expect(result).to eq "markdown"
219
+ end
220
+ end.not_to raise_error
221
+ end
222
+ end
207
223
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: middleman-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.7
4
+ version: 4.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Reynolds
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-04-13 00:00:00.000000000 Z
13
+ date: 2016-05-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -158,20 +158,34 @@ dependencies:
158
158
  - - "~>"
159
159
  - !ruby/object:Gem::Version
160
160
  version: '2.3'
161
+ - !ruby/object:Gem::Dependency
162
+ name: memoist
163
+ requirement: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - "~>"
166
+ - !ruby/object:Gem::Version
167
+ version: '0.14'
168
+ type: :runtime
169
+ prerelease: false
170
+ version_requirements: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - "~>"
173
+ - !ruby/object:Gem::Version
174
+ version: '0.14'
161
175
  - !ruby/object:Gem::Dependency
162
176
  name: listen
163
177
  requirement: !ruby/object:Gem::Requirement
164
178
  requirements:
165
179
  - - "~>"
166
180
  - !ruby/object:Gem::Version
167
- version: '3.0'
181
+ version: 3.0.0
168
182
  type: :runtime
169
183
  prerelease: false
170
184
  version_requirements: !ruby/object:Gem::Requirement
171
185
  requirements:
172
186
  - - "~>"
173
187
  - !ruby/object:Gem::Version
174
- version: '3.0'
188
+ version: 3.0.0
175
189
  - !ruby/object:Gem::Dependency
176
190
  name: capybara
177
191
  requirement: !ruby/object:Gem::Requirement
@@ -179,7 +193,7 @@ dependencies:
179
193
  - - "~>"
180
194
  - !ruby/object:Gem::Version
181
195
  version: 2.5.0
182
- type: :runtime
196
+ type: :development
183
197
  prerelease: false
184
198
  version_requirements: !ruby/object:Gem::Requirement
185
199
  requirements:
@@ -411,6 +425,7 @@ files:
411
425
  - features/proxy_pages.feature
412
426
  - features/redirects.feature
413
427
  - features/relative_assets.feature
428
+ - features/relative_assets_helpers_only.feature
414
429
  - features/sass-assets-paths.feature
415
430
  - features/sass_partials.feature
416
431
  - features/scss-support.feature
@@ -420,6 +435,7 @@ files:
420
435
  - features/stylus.feature
421
436
  - features/support/env.rb
422
437
  - features/support/preserve_mime_types.rb
438
+ - features/template-key-collision.feature
423
439
  - features/tilde_directories.feature
424
440
  - features/unicode_filecontents.feature
425
441
  - features/unicode_filenames.feature
@@ -1308,6 +1324,7 @@ files:
1308
1324
  - fixtures/relative-assets-app/source/fonts/roboto/roboto-regular-webfont.ttf
1309
1325
  - fixtures/relative-assets-app/source/fonts/roboto/roboto-regular-webfont.woff
1310
1326
  - fixtures/relative-assets-app/source/images/blank.gif
1327
+ - fixtures/relative-assets-app/source/images/blank2.gif
1311
1328
  - fixtures/relative-assets-app/source/img/blank.gif
1312
1329
  - fixtures/relative-assets-app/source/javascripts/app.js
1313
1330
  - fixtures/relative-assets-app/source/javascripts/application.js
@@ -1605,6 +1622,7 @@ test_files:
1605
1622
  - features/proxy_pages.feature
1606
1623
  - features/redirects.feature
1607
1624
  - features/relative_assets.feature
1625
+ - features/relative_assets_helpers_only.feature
1608
1626
  - features/sass-assets-paths.feature
1609
1627
  - features/sass_partials.feature
1610
1628
  - features/scss-support.feature
@@ -1614,6 +1632,7 @@ test_files:
1614
1632
  - features/stylus.feature
1615
1633
  - features/support/env.rb
1616
1634
  - features/support/preserve_mime_types.rb
1635
+ - features/template-key-collision.feature
1617
1636
  - features/tilde_directories.feature
1618
1637
  - features/unicode_filecontents.feature
1619
1638
  - features/unicode_filenames.feature
@@ -2502,6 +2521,7 @@ test_files:
2502
2521
  - fixtures/relative-assets-app/source/fonts/roboto/roboto-regular-webfont.ttf
2503
2522
  - fixtures/relative-assets-app/source/fonts/roboto/roboto-regular-webfont.woff
2504
2523
  - fixtures/relative-assets-app/source/images/blank.gif
2524
+ - fixtures/relative-assets-app/source/images/blank2.gif
2505
2525
  - fixtures/relative-assets-app/source/img/blank.gif
2506
2526
  - fixtures/relative-assets-app/source/javascripts/app.js
2507
2527
  - fixtures/relative-assets-app/source/javascripts/application.js