middleman-core 4.1.7 → 4.1.8

Sign up to get free protection for your applications and to get access to all the features.
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