sprockets 3.7.2 → 4.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -267
  3. data/README.md +477 -321
  4. data/bin/sprockets +11 -7
  5. data/lib/rake/sprocketstask.rb +3 -2
  6. data/lib/sprockets.rb +99 -39
  7. data/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
  8. data/lib/sprockets/asset.rb +31 -23
  9. data/lib/sprockets/autoload.rb +5 -0
  10. data/lib/sprockets/autoload/babel.rb +8 -0
  11. data/lib/sprockets/autoload/closure.rb +1 -0
  12. data/lib/sprockets/autoload/coffee_script.rb +1 -0
  13. data/lib/sprockets/autoload/eco.rb +1 -0
  14. data/lib/sprockets/autoload/ejs.rb +1 -0
  15. data/lib/sprockets/autoload/jsminc.rb +8 -0
  16. data/lib/sprockets/autoload/sass.rb +1 -0
  17. data/lib/sprockets/autoload/sassc.rb +8 -0
  18. data/lib/sprockets/autoload/uglifier.rb +1 -0
  19. data/lib/sprockets/autoload/yui.rb +1 -0
  20. data/lib/sprockets/autoload/zopfli.rb +7 -0
  21. data/lib/sprockets/babel_processor.rb +66 -0
  22. data/lib/sprockets/base.rb +49 -12
  23. data/lib/sprockets/bower.rb +5 -2
  24. data/lib/sprockets/bundle.rb +40 -4
  25. data/lib/sprockets/cache.rb +36 -1
  26. data/lib/sprockets/cache/file_store.rb +25 -3
  27. data/lib/sprockets/cache/memory_store.rb +9 -0
  28. data/lib/sprockets/cache/null_store.rb +8 -0
  29. data/lib/sprockets/cached_environment.rb +14 -19
  30. data/lib/sprockets/closure_compressor.rb +1 -0
  31. data/lib/sprockets/coffee_script_processor.rb +18 -4
  32. data/lib/sprockets/compressing.rb +43 -3
  33. data/lib/sprockets/configuration.rb +3 -7
  34. data/lib/sprockets/context.rb +97 -24
  35. data/lib/sprockets/dependencies.rb +1 -0
  36. data/lib/sprockets/digest_utils.rb +25 -5
  37. data/lib/sprockets/directive_processor.rb +45 -35
  38. data/lib/sprockets/eco_processor.rb +1 -0
  39. data/lib/sprockets/ejs_processor.rb +1 -0
  40. data/lib/sprockets/encoding_utils.rb +1 -0
  41. data/lib/sprockets/environment.rb +9 -4
  42. data/lib/sprockets/erb_processor.rb +28 -21
  43. data/lib/sprockets/errors.rb +1 -0
  44. data/lib/sprockets/exporters/base.rb +71 -0
  45. data/lib/sprockets/exporters/file_exporter.rb +24 -0
  46. data/lib/sprockets/exporters/zlib_exporter.rb +33 -0
  47. data/lib/sprockets/exporters/zopfli_exporter.rb +14 -0
  48. data/lib/sprockets/exporting.rb +73 -0
  49. data/lib/sprockets/file_reader.rb +1 -0
  50. data/lib/sprockets/http_utils.rb +25 -7
  51. data/lib/sprockets/jsminc_compressor.rb +32 -0
  52. data/lib/sprockets/jst_processor.rb +11 -10
  53. data/lib/sprockets/loader.rb +87 -67
  54. data/lib/sprockets/manifest.rb +64 -62
  55. data/lib/sprockets/manifest_utils.rb +9 -6
  56. data/lib/sprockets/mime.rb +8 -42
  57. data/lib/sprockets/npm.rb +52 -0
  58. data/lib/sprockets/path_dependency_utils.rb +3 -11
  59. data/lib/sprockets/path_digest_utils.rb +2 -1
  60. data/lib/sprockets/path_utils.rb +87 -7
  61. data/lib/sprockets/paths.rb +1 -0
  62. data/lib/sprockets/preprocessors/default_source_map.rb +49 -0
  63. data/lib/sprockets/processing.rb +31 -61
  64. data/lib/sprockets/processor_utils.rb +24 -35
  65. data/lib/sprockets/resolve.rb +177 -93
  66. data/lib/sprockets/sass_cache_store.rb +2 -6
  67. data/lib/sprockets/sass_compressor.rb +13 -1
  68. data/lib/sprockets/sass_functions.rb +1 -0
  69. data/lib/sprockets/sass_importer.rb +1 -0
  70. data/lib/sprockets/sass_processor.rb +30 -9
  71. data/lib/sprockets/sassc_compressor.rb +56 -0
  72. data/lib/sprockets/sassc_processor.rb +297 -0
  73. data/lib/sprockets/server.rb +26 -23
  74. data/lib/sprockets/source_map_processor.rb +66 -0
  75. data/lib/sprockets/source_map_utils.rb +483 -0
  76. data/lib/sprockets/transformers.rb +63 -35
  77. data/lib/sprockets/uglifier_compressor.rb +21 -11
  78. data/lib/sprockets/unloaded_asset.rb +13 -11
  79. data/lib/sprockets/uri_tar.rb +1 -0
  80. data/lib/sprockets/uri_utils.rb +11 -8
  81. data/lib/sprockets/utils.rb +41 -74
  82. data/lib/sprockets/utils/gzip.rb +46 -14
  83. data/lib/sprockets/version.rb +2 -1
  84. data/lib/sprockets/yui_compressor.rb +1 -0
  85. metadata +127 -23
  86. data/LICENSE +0 -21
  87. data/lib/sprockets/coffee_script_template.rb +0 -17
  88. data/lib/sprockets/deprecation.rb +0 -90
  89. data/lib/sprockets/eco_template.rb +0 -17
  90. data/lib/sprockets/ejs_template.rb +0 -17
  91. data/lib/sprockets/engines.rb +0 -92
  92. data/lib/sprockets/erb_template.rb +0 -11
  93. data/lib/sprockets/legacy.rb +0 -330
  94. data/lib/sprockets/legacy_proc_processor.rb +0 -35
  95. data/lib/sprockets/legacy_tilt_processor.rb +0 -29
  96. data/lib/sprockets/sass_template.rb +0 -19
@@ -0,0 +1,24 @@
1
+ require 'sprockets/exporters/base'
2
+
3
+ module Sprockets
4
+ module Exporters
5
+ # Writes a an asset file to disk
6
+ class FileExporter < Exporters::Base
7
+ def skip?(logger)
8
+ if ::File.exist?(target)
9
+ logger.debug "Skipping #{ target }, already exists"
10
+ true
11
+ else
12
+ logger.info "Writing #{ target }"
13
+ false
14
+ end
15
+ end
16
+
17
+ def call
18
+ write(target) do |file|
19
+ file.write(asset.source)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,33 @@
1
+ require 'sprockets/exporters/base'
2
+ require 'sprockets/utils/gzip'
3
+
4
+ module Sprockets
5
+ module Exporters
6
+ # Generates a `.gz` file using the zlib algorithm built into
7
+ # Ruby's standard library.
8
+ class ZlibExporter < Exporters::Base
9
+ def setup
10
+ @gzip_target = "#{ target }.gz"
11
+ @gzip = Sprockets::Utils::Gzip.new(asset, archiver: Utils::Gzip::ZlibArchiver)
12
+ end
13
+
14
+ def skip?(logger)
15
+ return true if environment.skip_gzip?
16
+ return true if @gzip.cannot_compress?
17
+ if ::File.exist?(@gzip_target)
18
+ logger.debug "Skipping #{ @gzip_target }, already exists"
19
+ true
20
+ else
21
+ logger.info "Writing #{ @gzip_target }"
22
+ false
23
+ end
24
+ end
25
+
26
+ def call
27
+ write(@gzip_target) do |file|
28
+ @gzip.compress(file, target)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ require 'sprockets/exporters/zlib_exporter'
2
+
3
+ module Sprockets
4
+ module Exporters
5
+ # Generates a `.gz` file using the zopfli algorithm from the
6
+ # Zopfli gem.
7
+ class ZopfliExporter < ZlibExporter
8
+ def setup
9
+ @gzip_target = "#{ target }.gz"
10
+ @gzip = Sprockets::Utils::Gzip.new(asset, archiver: Utils::Gzip::ZopfliArchiver)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,73 @@
1
+ module Sprockets
2
+ # `Exporting` is an internal mixin whose public methods are exposed on
3
+ # the `Environment` and `CachedEnvironment` classes.
4
+ module Exporting
5
+ # Exporters are ran on the assets:precompile task
6
+ def exporters
7
+ config[:exporters]
8
+ end
9
+
10
+ # Public: Registers a new Exporter `klass` for `mime_type`.
11
+ #
12
+ # If your exporter depends on one or more other exporters you can
13
+ # specify this via the `depend_on` keyword.
14
+ #
15
+ # register_exporter '*/*', Sprockets::Exporters::ZlibExporter
16
+ #
17
+ # This ensures that `Sprockets::Exporters::File` will always execute before
18
+ # `Sprockets::Exporters::Zlib`
19
+ def register_exporter(mime_types, klass = nil)
20
+ mime_types = Array(mime_types)
21
+
22
+ mime_types.each do |mime_type|
23
+ self.config = hash_reassoc(config, :exporters, mime_type) do |_exporters|
24
+ _exporters << klass
25
+ end
26
+ end
27
+ end
28
+
29
+ # Public: Remove Exporting processor `klass` for `mime_type`.
30
+ #
31
+ # environment.unregister_exporter '*/*', Sprockets::Exporters::Zlib
32
+ #
33
+ # Can be called without a mime type
34
+ #
35
+ # environment.unregister_exporter Sprockets::Exporters::Zlib
36
+ #
37
+ # Does not remove any exporters that depend on `klass`.
38
+ def unregister_exporter(mime_types, exporter = nil)
39
+ unless mime_types.is_a? Array
40
+ if mime_types.is_a? String
41
+ mime_types = [mime_types]
42
+ else # called with no mime type
43
+ exporter = mime_types
44
+ mime_types = nil
45
+ end
46
+ end
47
+
48
+ self.config = hash_reassoc(config, :exporters) do |_exporters|
49
+ _exporters.each do |mime_type, exporters_array|
50
+ next if mime_types && !mime_types.include?(mime_type)
51
+ if exporters_array.include? exporter
52
+ _exporters[mime_type] = exporters_array.dup.delete exporter
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ # Public: Checks if concurrent exporting is allowed
59
+ def export_concurrent
60
+ config[:export_concurrent]
61
+ end
62
+
63
+ # Public: Enable or disable the concurrently exporting files
64
+ #
65
+ # Defaults to true.
66
+ #
67
+ # environment.export_concurrent = false
68
+ #
69
+ def export_concurrent=(export_concurrent)
70
+ self.config = config.merge(export_concurrent: export_concurrent).freeze
71
+ end
72
+ end
73
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'set'
2
3
 
3
4
  module Sprockets
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Sprockets
2
3
  # Internal: HTTP URI utilities. Many adapted from Rack::Utils. Mixed into
3
4
  # Environment.
@@ -13,9 +14,9 @@ module Sprockets
13
14
  # Returns true if the given value is a mime match for the given mime match
14
15
  # specification, false otherwise.
15
16
  def match_mime_type?(value, matcher)
16
- v1, v2 = value.split('/', 2)
17
- m1, m2 = matcher.split('/', 2)
18
- (m1 == '*' || v1 == m1) && (m2.nil? || m2 == '*' || m2 == v2)
17
+ v1, v2 = value.split('/'.freeze, 2)
18
+ m1, m2 = matcher.split('/'.freeze, 2)
19
+ (m1 == '*'.freeze || v1 == m1) && (m2.nil? || m2 == '*'.freeze || m2 == v2)
19
20
  end
20
21
 
21
22
  # Public: Return values from Hash where the key matches the mime type.
@@ -36,7 +37,22 @@ module Sprockets
36
37
 
37
38
  # Internal: Parse Accept header quality values.
38
39
  #
39
- # Adapted from Rack::Utils#q_values.
40
+ # values - String e.g. "application/javascript"
41
+ #
42
+ # Adapted from Rack::Utils#q_values. Quality values are
43
+ # described in http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
44
+ #
45
+ # parse_q_values("application/javascript")
46
+ # # => [["application/javascript", 1.0]]
47
+ #
48
+ # parse_q_values("*/*")
49
+ # # => [["*/*", 1.0]]
50
+ #
51
+ # parse_q_values("text/plain; q=0.5, image/*")
52
+ # # => [["text/plain", 0.5], ["image/*", 1.0]]
53
+ #
54
+ # parse_q_values("application/javascript, text/css")
55
+ # # => [["application/javascript", 1.0], ["text/css", 1.0]]
40
56
  #
41
57
  # Returns an Array of [String, Float].
42
58
  def parse_q_values(values)
@@ -70,14 +86,16 @@ module Sprockets
70
86
  raise TypeError, "unknown q_values type: #{q_values.class}"
71
87
  end
72
88
 
89
+ i = 0
73
90
  q_values.each do |accepted, quality|
74
91
  if match = available.find { |option| matcher.call(option, accepted) }
75
- matches << [match, quality]
92
+ i += 1
93
+ matches << [-quality, i, match]
76
94
  end
77
95
  end
78
96
 
79
- matches.sort_by! { |match, quality| -quality }
80
- matches.map! { |match, quality| match }
97
+ matches.sort!
98
+ matches.map! { |_, _, match| match }
81
99
  matches
82
100
  end
83
101
 
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ require 'sprockets/autoload'
3
+ require 'sprockets/digest_utils'
4
+
5
+ module Sprockets
6
+ class JSMincCompressor
7
+ VERSION = '1'
8
+
9
+ def self.instance
10
+ @instance ||= new
11
+ end
12
+
13
+ def self.call(input)
14
+ instance.call(input)
15
+ end
16
+
17
+ def self.cache_key
18
+ instance.cache_key
19
+ end
20
+
21
+ attr_reader :cache_key
22
+
23
+ def initialize(options = {})
24
+ @compressor_class = Autoload::JSMinC
25
+ @cache_key = "#{self.class.name}:#{Autoload::JSMinC::VERSION}:#{VERSION}:#{DigestUtils.digest(options)}".freeze
26
+ end
27
+
28
+ def call(input)
29
+ @compressor_class.minify(input[:data])
30
+ end
31
+ end
32
+ end
@@ -1,21 +1,22 @@
1
+ # frozen_string_literal: true
1
2
  module Sprockets
2
- # Public: .jst engine.
3
+ # Public: JST transformer.
3
4
  #
4
5
  # Exports server side compiled templates to an object.
5
6
  #
6
- # Name your template "users/show.jst.ejs", "users/new.jst.eco", etc.
7
+ # Name your template "users/show.ejs", "users/new.eco", etc.
7
8
  #
8
9
  # To accept the default options
9
10
  #
10
- # environment.register_engine '.jst',
11
- # JstProcessor,
12
- # mime_type: 'application/javascript'
11
+ # environment.register_transformer
12
+ # 'application/javascript+function',
13
+ # 'application/javascript', JstProcessor
13
14
  #
14
15
  # Change the default namespace.
15
16
  #
16
- # environment.register_engine '.jst',
17
- # JstProcessor.new(namespace: 'App.templates'),
18
- # mime_type: 'application/javascript'
17
+ # environment.register_transformer
18
+ # 'application/javascript+function',
19
+ # 'application/javascript', JstProcessor.new(namespace: 'App.templates')
19
20
  #
20
21
  class JstProcessor
21
22
  def self.default_namespace
@@ -33,8 +34,8 @@ module Sprockets
33
34
  instance.call(input)
34
35
  end
35
36
 
36
- def initialize(options = {})
37
- @namespace = options[:namespace] || self.class.default_namespace
37
+ def initialize(namespace: self.class.default_namespace)
38
+ @namespace = namespace
38
39
  end
39
40
 
40
41
  def call(input)
@@ -1,6 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  require 'sprockets/asset'
2
3
  require 'sprockets/digest_utils'
3
- require 'sprockets/engines'
4
4
  require 'sprockets/errors'
5
5
  require 'sprockets/file_reader'
6
6
  require 'sprockets/mime'
@@ -18,7 +18,7 @@ module Sprockets
18
18
  # object.
19
19
  module Loader
20
20
  include DigestUtils, PathUtils, ProcessorUtils, URIUtils
21
- include Engines, Mime, Processing, Resolve, Transformers
21
+ include Mime, Processing, Resolve, Transformers
22
22
 
23
23
 
24
24
  # Public: Load Asset by Asset URI.
@@ -27,7 +27,6 @@ module Sprockets
27
27
  # and full path such as:
28
28
  # "file:///Path/app/assets/js/app.js?type=application/javascript"
29
29
  #
30
- #
31
30
  # Returns Asset.
32
31
  def load(uri)
33
32
  unloaded = UnloadedAsset.new(uri, self)
@@ -46,7 +45,7 @@ module Sprockets
46
45
  # The presence of `paths` indicates dependencies were stored.
47
46
  # We can check to see if the dependencies have not changed by "resolving" them and
48
47
  # generating a digest key from the resolved entries. If this digest key has not
49
- # changed the asset will be pulled from cache.
48
+ # changed, the asset will be pulled from cache.
50
49
  #
51
50
  # If this `paths` is present but the cache returns nothing then `fetch_asset_from_dependency_cache`
52
51
  # will confusingly be called again with `paths` set to nil where the asset will be
@@ -61,10 +60,47 @@ module Sprockets
61
60
  end
62
61
  end
63
62
  end
64
- Asset.new(self, asset)
63
+ Asset.new(asset)
65
64
  end
66
65
 
67
66
  private
67
+ def compress_key_from_hash(hash, key)
68
+ return unless hash.key?(key)
69
+ value = hash[key].dup
70
+ return if !value
71
+
72
+ if block_given?
73
+ value.map! do |x|
74
+ if yield x
75
+ compress_from_root(x)
76
+ else
77
+ x
78
+ end
79
+ end
80
+ else
81
+ value.map! { |x| compress_from_root(x) }
82
+ end
83
+ hash[key] = value
84
+ end
85
+
86
+
87
+ def expand_key_from_hash(hash, key)
88
+ return unless hash.key?(key)
89
+ value = hash[key].dup
90
+ return if !value
91
+ if block_given?
92
+ value.map! do |x|
93
+ if yield x
94
+ expand_from_root(x)
95
+ else
96
+ x
97
+ end
98
+ end
99
+ else
100
+ value.map! { |x| expand_from_root(x) }
101
+ end
102
+ hash[key] = value
103
+ end
68
104
 
69
105
  # Internal: Load asset hash from cache
70
106
  #
@@ -78,15 +114,17 @@ module Sprockets
78
114
  asset[:uri] = expand_from_root(asset[:uri])
79
115
  asset[:load_path] = expand_from_root(asset[:load_path])
80
116
  asset[:filename] = expand_from_root(asset[:filename])
81
- asset[:metadata][:included].map! { |uri| expand_from_root(uri) } if asset[:metadata][:included]
82
- asset[:metadata][:links].map! { |uri| expand_from_root(uri) } if asset[:metadata][:links]
83
- asset[:metadata][:stubbed].map! { |uri| expand_from_root(uri) } if asset[:metadata][:stubbed]
84
- asset[:metadata][:required].map! { |uri| expand_from_root(uri) } if asset[:metadata][:required]
85
- asset[:metadata][:dependencies].map! { |uri| uri.start_with?("file-digest://") ? expand_from_root(uri) : uri } if asset[:metadata][:dependencies]
117
+ expand_key_from_hash(asset[:metadata], :included)
118
+ expand_key_from_hash(asset[:metadata], :links)
119
+ expand_key_from_hash(asset[:metadata], :stubbed)
120
+ expand_key_from_hash(asset[:metadata], :required)
121
+ expand_key_from_hash(asset[:metadata], :to_load)
122
+ expand_key_from_hash(asset[:metadata], :to_link)
123
+ expand_key_from_hash(asset[:metadata], :dependencies) { |uri| uri.start_with?("file-digest://") }
86
124
 
87
125
  asset[:metadata].each_key do |k|
88
- next unless k =~ /_dependencies\z/
89
- asset[:metadata][k].map! { |uri| expand_from_root(uri) }
126
+ next unless k.match?(/_dependencies\z/) # rubocop:disable Performance/EndWith
127
+ expand_key_from_hash(asset[:metadata], k)
90
128
  end
91
129
  end
92
130
  asset
@@ -103,13 +141,23 @@ module Sprockets
103
141
  raise FileNotFound, "could not find file: #{unloaded.filename}"
104
142
  end
105
143
 
106
- load_path, logical_path = paths_split(config[:paths], unloaded.filename)
144
+ path_to_split =
145
+ if index_alias = unloaded.params[:index_alias]
146
+ expand_from_root index_alias
147
+ else
148
+ unloaded.filename
149
+ end
150
+
151
+ load_path, logical_path = paths_split(config[:paths], path_to_split)
107
152
 
108
153
  unless load_path
109
- raise FileOutsidePaths, "#{unloaded.filename} is no longer under a load path: #{self.paths.join(', ')}"
154
+ target = path_to_split
155
+ target += " (index alias of #{unloaded.filename})" if unloaded.params[:index_alias]
156
+ raise FileOutsidePaths, "#{target} is no longer under a load path: #{self.paths.join(', ')}"
110
157
  end
111
158
 
112
- logical_path, file_type, engine_extnames, _ = parse_path_extnames(logical_path)
159
+ extname, file_type = match_path_extname(logical_path, mime_exts)
160
+ logical_path = logical_path.chomp(extname)
113
161
  name = logical_path
114
162
 
115
163
  if pipeline = unloaded.params[:pipeline]
@@ -124,9 +172,9 @@ module Sprockets
124
172
  raise ConversionError, "could not convert #{file_type.inspect} to #{type.inspect}"
125
173
  end
126
174
 
127
- processors = processors_for(type, file_type, engine_extnames, pipeline)
175
+ processors = processors_for(type, file_type, pipeline)
128
176
 
129
- processors_dep_uri = build_processors_uri(type, file_type, engine_extnames, pipeline)
177
+ processors_dep_uri = build_processors_uri(type, file_type, pipeline)
130
178
  dependencies = config[:dependencies] + [processors_dep_uri]
131
179
 
132
180
  # Read into memory and process if theres a processor pipeline
@@ -139,7 +187,9 @@ module Sprockets
139
187
  load_path: load_path,
140
188
  name: name,
141
189
  content_type: type,
142
- metadata: { dependencies: dependencies }
190
+ metadata: {
191
+ dependencies: dependencies
192
+ }
143
193
  })
144
194
  validate_processor_result!(result)
145
195
  source = result.delete(:data)
@@ -147,12 +197,14 @@ module Sprockets
147
197
  metadata[:charset] = source.encoding.name.downcase unless metadata.key?(:charset)
148
198
  metadata[:digest] = digest(source)
149
199
  metadata[:length] = source.bytesize
200
+ metadata[:environment_version] = version
150
201
  else
151
202
  dependencies << build_file_digest_uri(unloaded.filename)
152
203
  metadata = {
153
204
  digest: file_digest(unloaded.filename),
154
205
  length: self.stat(unloaded.filename).size,
155
- dependencies: dependencies
206
+ dependencies: dependencies,
207
+ environment_version: version,
156
208
  }
157
209
  end
158
210
 
@@ -168,20 +220,9 @@ module Sprockets
168
220
  dependencies_digest: DigestUtils.digest(resolve_dependencies(metadata[:dependencies]))
169
221
  }
170
222
 
171
- asset[:id] = pack_hexdigest(digest(asset))
223
+ asset[:id] = hexdigest(asset)
172
224
  asset[:uri] = build_asset_uri(unloaded.filename, unloaded.params.merge(id: asset[:id]))
173
225
 
174
- # Deprecated: Avoid tracking Asset mtime
175
- asset[:mtime] = metadata[:dependencies].map { |u|
176
- if u.start_with?("file-digest:")
177
- s = self.stat(parse_file_digest_uri(u))
178
- s ? s.mtime.to_i : nil
179
- else
180
- nil
181
- end
182
- }.compact.max
183
- asset[:mtime] ||= self.stat(unloaded.filename).mtime.to_i
184
-
185
226
  store_asset(asset, unloaded)
186
227
  asset
187
228
  end
@@ -203,38 +244,17 @@ module Sprockets
203
244
  if cached_asset[:metadata]
204
245
  # Deep dup to avoid modifying `asset`
205
246
  cached_asset[:metadata] = cached_asset[:metadata].dup
206
- if cached_asset[:metadata][:included] && !cached_asset[:metadata][:included].empty?
207
- cached_asset[:metadata][:included] = cached_asset[:metadata][:included].dup
208
- cached_asset[:metadata][:included].map! { |uri| compress_from_root(uri) }
209
- end
210
-
211
- if cached_asset[:metadata][:links] && !cached_asset[:metadata][:links].empty?
212
- cached_asset[:metadata][:links] = cached_asset[:metadata][:links].dup
213
- cached_asset[:metadata][:links].map! { |uri| compress_from_root(uri) }
214
- end
215
-
216
- if cached_asset[:metadata][:stubbed] && !cached_asset[:metadata][:stubbed].empty?
217
- cached_asset[:metadata][:stubbed] = cached_asset[:metadata][:stubbed].dup
218
- cached_asset[:metadata][:stubbed].map! { |uri| compress_from_root(uri) }
219
- end
220
-
221
- if cached_asset[:metadata][:required] && !cached_asset[:metadata][:required].empty?
222
- cached_asset[:metadata][:required] = cached_asset[:metadata][:required].dup
223
- cached_asset[:metadata][:required].map! { |uri| compress_from_root(uri) }
224
- end
225
-
226
- if cached_asset[:metadata][:dependencies] && !cached_asset[:metadata][:dependencies].empty?
227
- cached_asset[:metadata][:dependencies] = cached_asset[:metadata][:dependencies].dup
228
- cached_asset[:metadata][:dependencies].map! do |uri|
229
- uri.start_with?("file-digest://".freeze) ? compress_from_root(uri) : uri
230
- end
231
- end
247
+ compress_key_from_hash(cached_asset[:metadata], :included)
248
+ compress_key_from_hash(cached_asset[:metadata], :links)
249
+ compress_key_from_hash(cached_asset[:metadata], :stubbed)
250
+ compress_key_from_hash(cached_asset[:metadata], :required)
251
+ compress_key_from_hash(cached_asset[:metadata], :to_load)
252
+ compress_key_from_hash(cached_asset[:metadata], :to_link)
253
+ compress_key_from_hash(cached_asset[:metadata], :dependencies) { |uri| uri.start_with?("file-digest://") }
232
254
 
233
- # compress all _dependencies in metadata like `sass_dependencies`
234
255
  cached_asset[:metadata].each do |key, value|
235
- next unless key =~ /_dependencies\z/
236
- cached_asset[:metadata][key] = value.dup
237
- cached_asset[:metadata][key].map! {|uri| compress_from_root(uri) }
256
+ next unless key.match?(/_dependencies\z/) # rubocop:disable Performance/EndWith
257
+ compress_key_from_hash(cached_asset[:metadata], key)
238
258
  end
239
259
  end
240
260
 
@@ -255,11 +275,11 @@ module Sprockets
255
275
  # "processors:type=text/css&file_type=text/css&pipeline=self",
256
276
  # "file-digest:///Full/path/app/assets/stylesheets"]
257
277
  #
258
- # Returns back array of things that the given uri dpends on
278
+ # Returns back array of things that the given uri depends on
259
279
  # For example the environment version, if you're using a different version of sprockets
260
280
  # then the dependencies should be different, this is used only for generating cache key
261
281
  # for example the "environment-version" may be resolved to "environment-1.0-3.2.0" for
262
- # version "3.2.0" of sprockets.
282
+ # version "3.2.0" of sprockets.
263
283
  #
264
284
  # Any paths that are returned are converted to relative paths
265
285
  #
@@ -276,9 +296,9 @@ module Sprockets
276
296
  #
277
297
  # This method attempts to retrieve the last `limit` number of histories of an asset
278
298
  # from the cache a "history" which is an array of unresolved "dependencies" that the asset needs
279
- # to compile. In this case A dependency can refer to either an asset i.e. index.js
280
- # may rely on jquery.js (so jquery.js is a depndency), or other factors that may affect
281
- # compilation, such as the VERSION of sprockets (i.e. the environment) and what "processors"
299
+ # to compile. In this case a dependency can refer to either an asset e.g. index.js
300
+ # may rely on jquery.js (so jquery.js is a dependency), or other factors that may affect
301
+ # compilation, such as the VERSION of Sprockets (i.e. the environment) and what "processors"
282
302
  # are used.
283
303
  #
284
304
  # For example a history array may look something like this
@@ -289,7 +309,7 @@ module Sprockets
289
309
  # "file-digest:///Full/path/app/assets/stylesheets"]]
290
310
  #
291
311
  # Where the first entry is a Set of dependencies for last generated version of that asset.
292
- # Multiple versions are stored since sprockets keeps the last `limit` number of assets
312
+ # Multiple versions are stored since Sprockets keeps the last `limit` number of assets
293
313
  # generated present in the system.
294
314
  #
295
315
  # If a "history" of dependencies is present in the cache, each version of "history" will be