sprockets 3.7.2 → 4.2.0

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -261
  3. data/{LICENSE → MIT-LICENSE} +2 -2
  4. data/README.md +527 -320
  5. data/bin/sprockets +11 -7
  6. data/lib/rake/sprocketstask.rb +9 -4
  7. data/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
  8. data/lib/sprockets/asset.rb +39 -27
  9. data/lib/sprockets/autoload/babel.rb +8 -0
  10. data/lib/sprockets/autoload/closure.rb +1 -0
  11. data/lib/sprockets/autoload/coffee_script.rb +1 -0
  12. data/lib/sprockets/autoload/eco.rb +1 -0
  13. data/lib/sprockets/autoload/ejs.rb +1 -0
  14. data/lib/sprockets/autoload/jsminc.rb +8 -0
  15. data/lib/sprockets/autoload/sass.rb +1 -0
  16. data/lib/sprockets/autoload/sassc.rb +8 -0
  17. data/lib/sprockets/autoload/uglifier.rb +1 -0
  18. data/lib/sprockets/autoload/yui.rb +1 -0
  19. data/lib/sprockets/autoload/zopfli.rb +7 -0
  20. data/lib/sprockets/autoload.rb +5 -0
  21. data/lib/sprockets/babel_processor.rb +66 -0
  22. data/lib/sprockets/base.rb +49 -12
  23. data/lib/sprockets/bower.rb +6 -3
  24. data/lib/sprockets/bundle.rb +41 -5
  25. data/lib/sprockets/cache/file_store.rb +25 -3
  26. data/lib/sprockets/cache/memory_store.rb +28 -10
  27. data/lib/sprockets/cache/null_store.rb +8 -0
  28. data/lib/sprockets/cache.rb +37 -2
  29. data/lib/sprockets/cached_environment.rb +15 -20
  30. data/lib/sprockets/closure_compressor.rb +1 -0
  31. data/lib/sprockets/coffee_script_processor.rb +19 -5
  32. data/lib/sprockets/compressing.rb +43 -3
  33. data/lib/sprockets/configuration.rb +5 -9
  34. data/lib/sprockets/context.rb +99 -25
  35. data/lib/sprockets/dependencies.rb +2 -1
  36. data/lib/sprockets/digest_utils.rb +35 -18
  37. data/lib/sprockets/directive_processor.rb +64 -36
  38. data/lib/sprockets/eco_processor.rb +2 -1
  39. data/lib/sprockets/ejs_processor.rb +2 -1
  40. data/lib/sprockets/encoding_utils.rb +1 -0
  41. data/lib/sprockets/environment.rb +9 -4
  42. data/lib/sprockets/erb_processor.rb +34 -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 +88 -68
  54. data/lib/sprockets/manifest.rb +67 -64
  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 +88 -8
  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 +32 -62
  64. data/lib/sprockets/processor_utils.rb +28 -38
  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 +31 -10
  71. data/lib/sprockets/sassc_compressor.rb +56 -0
  72. data/lib/sprockets/sassc_processor.rb +297 -0
  73. data/lib/sprockets/server.rb +52 -39
  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 +12 -9
  81. data/lib/sprockets/utils/gzip.rb +46 -14
  82. data/lib/sprockets/utils.rb +64 -89
  83. data/lib/sprockets/version.rb +2 -1
  84. data/lib/sprockets/yui_compressor.rb +1 -0
  85. data/lib/sprockets.rb +102 -39
  86. metadata +139 -34
  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
@@ -1,10 +1,10 @@
1
- require 'pathname'
1
+ # frozen_string_literal: true
2
2
  require 'rack/utils'
3
3
  require 'set'
4
4
  require 'sprockets/errors'
5
+ require 'delegate'
5
6
 
6
7
  module Sprockets
7
- # Deprecated: `Context` provides helper methods to all processors.
8
8
  # They are typically accessed by ERB templates. You can mix in custom helpers
9
9
  # by injecting them into `Environment#context_class`. Do not mix them into
10
10
  # `Context` directly.
@@ -19,10 +19,25 @@ module Sprockets
19
19
  # The `Context` also collects dependencies declared by
20
20
  # assets. See `DirectiveProcessor` for an example of this.
21
21
  class Context
22
- attr_reader :environment, :filename, :pathname
22
+ # Internal: Proxy for ENV that keeps track of the environment variables used
23
+ class ENVProxy < SimpleDelegator
24
+ def initialize(context)
25
+ @context = context
26
+ super(ENV)
27
+ end
23
28
 
24
- # Deprecated
25
- attr_accessor :__LINE__
29
+ def [](key)
30
+ @context.depend_on_env(key)
31
+ super
32
+ end
33
+
34
+ def fetch(key, *)
35
+ @context.depend_on_env(key)
36
+ super
37
+ end
38
+ end
39
+
40
+ attr_reader :environment, :filename
26
41
 
27
42
  def initialize(input)
28
43
  @environment = input[:environment]
@@ -31,7 +46,6 @@ module Sprockets
31
46
  @logical_path = input[:name]
32
47
  @filename = input[:filename]
33
48
  @dirname = File.dirname(@filename)
34
- @pathname = Pathname.new(@filename)
35
49
  @content_type = input[:content_type]
36
50
 
37
51
  @required = Set.new(@metadata[:required])
@@ -47,6 +61,10 @@ module Sprockets
47
61
  dependencies: @dependencies }
48
62
  end
49
63
 
64
+ def env_proxy
65
+ ENVProxy.new(self)
66
+ end
67
+
50
68
  # Returns the environment path that contains the file.
51
69
  #
52
70
  # If `app/javascripts` and `app/stylesheets` are in your path, and
@@ -79,13 +97,13 @@ module Sprockets
79
97
  # resolve("./bar.js")
80
98
  # # => "file:///path/to/app/javascripts/bar.js?type=application/javascript"
81
99
  #
82
- # path - String logical or absolute path
83
- # options
84
- # accept - String content accept type
100
+ # path - String logical or absolute path
101
+ # accept - String content accept type
85
102
  #
86
103
  # Returns an Asset URI String.
87
- def resolve(path, options = {})
88
- uri, deps = environment.resolve!(path, options.merge(base_path: @dirname))
104
+ def resolve(path, **kargs)
105
+ kargs[:base_path] = @dirname
106
+ uri, deps = environment.resolve!(path, **kargs)
89
107
  @dependencies.merge(deps)
90
108
  uri
91
109
  end
@@ -105,15 +123,13 @@ module Sprockets
105
123
  # including it.
106
124
  #
107
125
  # This is used for caching purposes. Any changes made to
108
- # the dependency file with invalidate the cache of the
126
+ # the dependency file will invalidate the cache of the
109
127
  # source file.
110
128
  def depend_on(path)
111
- path = path.to_s if path.is_a?(Pathname)
112
-
113
129
  if environment.absolute_path?(path) && environment.stat(path)
114
130
  @dependencies << environment.build_file_digest_uri(path)
115
131
  else
116
- resolve(path, compat: false)
132
+ resolve(path)
117
133
  end
118
134
  nil
119
135
  end
@@ -123,10 +139,19 @@ module Sprockets
123
139
  #
124
140
  # This is used for caching purposes. Any changes that would
125
141
  # invalidate the dependency asset will invalidate the source
126
- # file. Unlike `depend_on`, this will include recursively include
142
+ # file. Unlike `depend_on`, this will recursively include
127
143
  # the target asset's dependencies.
128
144
  def depend_on_asset(path)
129
- load(resolve(path, compat: false))
145
+ load(resolve(path))
146
+ end
147
+
148
+ # `depend_on_env` allows you to state a dependency on an environment
149
+ # variable.
150
+ #
151
+ # This is used for caching purposes. Any changes in the value of the
152
+ # environment variable will invalidate the cache of the source file.
153
+ def depend_on_env(key)
154
+ @dependencies << "env:#{key}"
130
155
  end
131
156
 
132
157
  # `require_asset` declares `path` as a dependency of the file. The
@@ -139,7 +164,7 @@ module Sprockets
139
164
  # <%= require_asset "#{framework}.js" %>
140
165
  #
141
166
  def require_asset(path)
142
- @required << resolve(path, accept: @content_type, pipeline: :self, compat: false)
167
+ @required << resolve(path, accept: @content_type, pipeline: :self)
143
168
  nil
144
169
  end
145
170
 
@@ -147,7 +172,7 @@ module Sprockets
147
172
  # `path` must be an asset which may or may not already be included
148
173
  # in the bundle.
149
174
  def stub_asset(path)
150
- @stubbed << resolve(path, accept: @content_type, pipeline: :self, compat: false)
175
+ @stubbed << resolve(path, accept: @content_type, pipeline: :self)
151
176
  nil
152
177
  end
153
178
 
@@ -162,9 +187,10 @@ module Sprockets
162
187
  asset
163
188
  end
164
189
 
165
- # Returns a Base64-encoded `data:` URI with the contents of the
166
- # asset at the specified path, and marks that path as a dependency
167
- # of the current file.
190
+ # Returns a `data:` URI with the contents of the asset at the specified
191
+ # path, and marks that path as a dependency of the current file.
192
+ #
193
+ # Uses URI encoding for SVG files, base64 encoding for all the other files.
168
194
  #
169
195
  # Use `asset_data_uri` from ERB with CSS or JavaScript assets:
170
196
  #
@@ -174,15 +200,18 @@ module Sprockets
174
200
  #
175
201
  def asset_data_uri(path)
176
202
  asset = depend_on_asset(path)
177
- data = EncodingUtils.base64(asset.source)
178
- "data:#{asset.content_type};base64,#{Rack::Utils.escape(data)}"
203
+ if asset.content_type == 'image/svg+xml'
204
+ svg_asset_data_uri(asset)
205
+ else
206
+ base64_asset_data_uri(asset)
207
+ end
179
208
  end
180
209
 
181
210
  # Expands logical path to full url to asset.
182
211
  #
183
212
  # NOTE: This helper is currently not implemented and should be
184
213
  # customized by the application. Though, in the future, some
185
- # basics implemention may be provided with different methods that
214
+ # basic implementation may be provided with different methods that
186
215
  # are required to be overridden.
187
216
  def asset_path(path, options = {})
188
217
  message = <<-EOS
@@ -227,5 +256,50 @@ Extend your environment context with a custom method.
227
256
  def stylesheet_path(path)
228
257
  asset_path(path, type: :stylesheet)
229
258
  end
259
+
260
+ protected
261
+
262
+ # Returns a URI-encoded data URI (always "-quoted).
263
+ def svg_asset_data_uri(asset)
264
+ svg = asset.source.dup
265
+ optimize_svg_for_uri_escaping!(svg)
266
+ data = Rack::Utils.escape(svg)
267
+ optimize_quoted_uri_escapes!(data)
268
+ "\"data:#{asset.content_type};charset=utf-8,#{data}\""
269
+ end
270
+
271
+ # Returns a Base64-encoded data URI.
272
+ def base64_asset_data_uri(asset)
273
+ data = Rack::Utils.escape(EncodingUtils.base64(asset.source))
274
+ "data:#{asset.content_type};base64,#{data}"
275
+ end
276
+
277
+ # Optimizes an SVG for being URI-escaped.
278
+ #
279
+ # This method only performs these basic but crucial optimizations:
280
+ # * Replaces " with ', because ' does not need escaping.
281
+ # * Removes comments, meta, doctype, and newlines.
282
+ # * Collapses whitespace.
283
+ def optimize_svg_for_uri_escaping!(svg)
284
+ # Remove comments, xml meta, and doctype
285
+ svg.gsub!(/<!--.*?-->|<\?.*?\?>|<!.*?>/m, '')
286
+ # Replace consecutive whitespace and newlines with a space
287
+ svg.gsub!(/\s+/, ' ')
288
+ # Collapse inter-tag whitespace
289
+ svg.gsub!('> <', '><')
290
+ # Replace " with '
291
+ svg.gsub!(/([\w:])="(.*?)"/, "\\1='\\2'")
292
+ svg.strip!
293
+ end
294
+
295
+ # Un-escapes characters in the given URI-escaped string that do not need
296
+ # escaping in "-quoted data URIs.
297
+ def optimize_quoted_uri_escapes!(escaped)
298
+ escaped.gsub!('%3D', '=')
299
+ escaped.gsub!('%3A', ':')
300
+ escaped.gsub!('%2F', '/')
301
+ escaped.gsub!('%27', "'")
302
+ escaped.tr!('+', ' ')
303
+ end
230
304
  end
231
305
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'sprockets/digest_utils'
2
3
  require 'sprockets/path_digest_utils'
3
4
  require 'sprockets/uri_utils'
@@ -39,7 +40,7 @@ module Sprockets
39
40
  end
40
41
  end
41
42
 
42
- # Public: Add environmental dependency inheirted by all assets.
43
+ # Public: Add environmental dependency inherited by all assets.
43
44
  #
44
45
  # uri - String dependency URI
45
46
  #
@@ -1,4 +1,4 @@
1
- require 'digest/md5'
1
+ # frozen_string_literal: true
2
2
  require 'digest/sha1'
3
3
  require 'digest/sha2'
4
4
  require 'set'
@@ -18,7 +18,6 @@ module Sprockets
18
18
 
19
19
  # Internal: Maps digest bytesize to the digest class.
20
20
  DIGEST_SIZES = {
21
- 16 => Digest::MD5,
22
21
  20 => Digest::SHA1,
23
22
  32 => Digest::SHA256,
24
23
  48 => Digest::SHA384,
@@ -62,23 +61,16 @@ module Sprockets
62
61
  },
63
62
  Set => ->(val, digest) {
64
63
  digest << 'Set'.freeze
65
- ADD_VALUE_TO_DIGEST[Array].call(val.to_a, digest)
64
+ ADD_VALUE_TO_DIGEST[Array].call(val, digest)
66
65
  },
67
66
  Encoding => ->(val, digest) {
68
67
  digest << 'Encoding'.freeze
69
68
  digest << val.name
70
- },
71
- }
72
- if 0.class != Integer # Ruby < 2.4
73
- ADD_VALUE_TO_DIGEST[Fixnum] = ->(val, digest) {
74
- digest << 'Integer'.freeze
75
- digest << val.to_s
76
- }
77
- ADD_VALUE_TO_DIGEST[Bignum] = ->(val, digest) {
78
- digest << 'Integer'.freeze
79
- digest << val.to_s
80
69
  }
81
- end
70
+ }
71
+
72
+ ADD_VALUE_TO_DIGEST.compare_by_identity.rehash
73
+
82
74
  ADD_VALUE_TO_DIGEST.default_proc = ->(_, val) {
83
75
  raise TypeError, "couldn't digest #{ val }"
84
76
  }
@@ -93,10 +85,18 @@ module Sprockets
93
85
  #
94
86
  # Returns a String digest of the object.
95
87
  def digest(obj)
96
- digest = digest_class.new
88
+ build_digest(obj).digest
89
+ end
97
90
 
98
- ADD_VALUE_TO_DIGEST[obj.class].call(obj, digest)
99
- digest.digest
91
+ # Internal: Generate a hexdigest for a nested JSON serializable object.
92
+ #
93
+ # The same as `pack_hexdigest(digest(obj))`.
94
+ #
95
+ # obj - A JSON serializable object.
96
+ #
97
+ # Returns a String digest of the object.
98
+ def hexdigest(obj)
99
+ build_digest(obj).hexdigest!
100
100
  end
101
101
 
102
102
  # Internal: Pack a binary digest to a hex encoded string.
@@ -105,7 +105,7 @@ module Sprockets
105
105
  #
106
106
  # Returns hex String.
107
107
  def pack_hexdigest(bin)
108
- bin.unpack('H*').first
108
+ bin.unpack('H*'.freeze).first
109
109
  end
110
110
 
111
111
  # Internal: Unpack a hex encoded digest string into binary bytes.
@@ -176,5 +176,22 @@ module Sprockets
176
176
  def hexdigest_integrity_uri(hexdigest)
177
177
  integrity_uri(unpack_hexdigest(hexdigest))
178
178
  end
179
+
180
+ # Internal: Checks an asset name for a valid digest
181
+ #
182
+ # name - The name of the asset
183
+ #
184
+ # Returns true if the name contains a digest like string and .digested before the extension
185
+ def already_digested?(name)
186
+ return name =~ /-([0-9a-zA-Z]{7,128})\.digested/
187
+ end
188
+
189
+ private
190
+ def build_digest(obj)
191
+ digest = digest_class.new
192
+
193
+ ADD_VALUE_TO_DIGEST[obj.class].call(obj, digest)
194
+ digest
195
+ end
179
196
  end
180
197
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'set'
2
3
  require 'shellwords'
3
4
 
@@ -34,8 +35,6 @@ module Sprockets
34
35
  # env.register_processor('text/css', MyProcessor)
35
36
  #
36
37
  class DirectiveProcessor
37
- VERSION = '1'
38
-
39
38
  # Directives are denoted by a `=` followed by the name, then
40
39
  # argument list.
41
40
  #
@@ -50,18 +49,16 @@ module Sprockets
50
49
  /x
51
50
 
52
51
  def self.instance
53
- @instance ||= new(
54
- # Deprecated: Default to C and Ruby comment styles
55
- comments: ["//", ["/*", "*/"]] + ["#", ["###", "###"]]
56
- )
52
+ # Default to C comment styles
53
+ @instance ||= new(comments: ["//", ["/*", "*/"]])
57
54
  end
58
55
 
59
56
  def self.call(input)
60
57
  instance.call(input)
61
58
  end
62
59
 
63
- def initialize(options = {})
64
- @header_pattern = compile_header_pattern(Array(options[:comments]))
60
+ def initialize(comments: [])
61
+ @header_pattern = compile_header_pattern(Array(comments))
65
62
  end
66
63
 
67
64
  def call(input)
@@ -73,20 +70,28 @@ module Sprockets
73
70
  @uri = input[:uri]
74
71
  @filename = input[:filename]
75
72
  @dirname = File.dirname(@filename)
76
- @content_type = input[:content_type]
73
+ # If loading a source map file like `application.js.map` resolve
74
+ # dependencies using `.js` instead of `.js.map`
75
+ @content_type = SourceMapProcessor.original_content_type(input[:content_type], error_when_not_found: false)
77
76
  @required = Set.new(input[:metadata][:required])
78
77
  @stubbed = Set.new(input[:metadata][:stubbed])
79
78
  @links = Set.new(input[:metadata][:links])
80
79
  @dependencies = Set.new(input[:metadata][:dependencies])
80
+ @to_link = Set.new
81
+ @to_load = Set.new
81
82
 
82
83
  data, directives = process_source(input[:data])
83
84
  process_directives(directives)
84
85
 
85
- { data: data,
86
- required: @required,
87
- stubbed: @stubbed,
88
- links: @links,
89
- dependencies: @dependencies }
86
+ {
87
+ data: data,
88
+ required: @required,
89
+ stubbed: @stubbed,
90
+ links: @links,
91
+ to_load: @to_load,
92
+ to_link: @to_link,
93
+ dependencies: @dependencies
94
+ }
90
95
  end
91
96
 
92
97
  protected
@@ -116,9 +121,9 @@ module Sprockets
116
121
 
117
122
  header, directives = extract_directives(header)
118
123
 
119
- data = ""
124
+ data = +""
120
125
  data.force_encoding(body.encoding)
121
- data << header << "\n" unless header.empty?
126
+ data << header unless header.empty?
122
127
  data << body
123
128
  # Ensure body ends in a new line
124
129
  data << "\n" if data.length > 0 && data[-1] != "\n"
@@ -134,7 +139,7 @@ module Sprockets
134
139
  # [[1, "require", "foo"], [2, "require", "bar"]]
135
140
  #
136
141
  def extract_directives(header)
137
- processed_header = ""
142
+ processed_header = +""
138
143
  directives = []
139
144
 
140
145
  header.lines.each_with_index do |line, index|
@@ -149,7 +154,11 @@ module Sprockets
149
154
  processed_header << line
150
155
  end
151
156
 
152
- return processed_header.chomp, directives
157
+ processed_header.chomp!
158
+ # Ensure header ends in a new line like before it was processed
159
+ processed_header << "\n" if processed_header.length > 0 && header[-1] == "\n"
160
+
161
+ return processed_header, directives
153
162
  end
154
163
 
155
164
  # Gathers comment directives in the source and processes them.
@@ -162,7 +171,7 @@ module Sprockets
162
171
  # `process_require_glob_directive`.
163
172
  #
164
173
  # class DirectiveProcessor < Sprockets::DirectiveProcessor
165
- # def process_require_glob_directive
174
+ # def process_require_glob_directive(glob)
166
175
  # Dir["#{dirname}/#{glob}"].sort.each do |filename|
167
176
  # require(filename)
168
177
  # end
@@ -187,7 +196,7 @@ module Sprockets
187
196
 
188
197
  # The `require` directive functions similar to Ruby's own `require`.
189
198
  # It provides a way to declare a dependency on a file in your path
190
- # and ensures its only loaded once before the source file.
199
+ # and ensures it's only loaded once before the source file.
191
200
  #
192
201
  # `require` works with files in the environment path:
193
202
  #
@@ -265,15 +274,33 @@ module Sprockets
265
274
  # it.
266
275
  #
267
276
  # This is used for caching purposes. Any changes that would
268
- # invalid the asset dependency will invalidate the cache our the
269
- # source file.
277
+ # invalidate the asset dependency will invalidate the cache of
278
+ # the source file.
270
279
  #
271
280
  # Unlike `depend_on`, the path must be a requirable asset.
272
281
  #
273
282
  # //= depend_on_asset "bar.js"
274
283
  #
275
284
  def process_depend_on_asset_directive(path)
276
- load(resolve(path))
285
+ to_load(resolve(path))
286
+ end
287
+
288
+ # Allows you to state a dependency on a relative directory
289
+ # without including it.
290
+ #
291
+ # This is used for caching purposes. Any changes made to
292
+ # the dependency directory will invalidate the cache of the
293
+ # source file.
294
+ #
295
+ # This is useful if you are using ERB and File.read to pull
296
+ # in contents from multiple files in a directory.
297
+ #
298
+ # //= depend_on_directory ./data
299
+ #
300
+ def process_depend_on_directory_directive(path = ".", accept = nil)
301
+ path = expand_relative_dirname(:depend_on_directory, path)
302
+ accept = expand_accept_shorthand(accept)
303
+ resolve_paths(*@environment.stat_directory_with_dependencies(path), accept: accept)
277
304
  end
278
305
 
279
306
  # Allows dependency to be excluded from the asset bundle.
@@ -297,7 +324,8 @@ module Sprockets
297
324
  # /*= link "logo.png" */
298
325
  #
299
326
  def process_link_directive(path)
300
- @links << load(resolve(path)).uri
327
+ uri = to_load(resolve(path))
328
+ @to_link << uri
301
329
  end
302
330
 
303
331
  # `link_directory` links all the files inside a single
@@ -307,7 +335,7 @@ module Sprockets
307
335
  # //= link_directory "./fonts"
308
336
  #
309
337
  # Use caution when linking against JS or CSS assets. Include an explicit
310
- # extension or content type in these cases
338
+ # extension or content type in these cases.
311
339
  #
312
340
  # //= link_directory "./scripts" .js
313
341
  #
@@ -323,7 +351,7 @@ module Sprockets
323
351
  # //= link_tree "./images"
324
352
  #
325
353
  # Use caution when linking against JS or CSS assets. Include an explicit
326
- # extension or content type in these cases
354
+ # extension or content type in these cases.
327
355
  #
328
356
  # //= link_tree "./styles" .css
329
357
  #
@@ -354,17 +382,17 @@ module Sprockets
354
382
 
355
383
  def link_paths(paths, deps, accept)
356
384
  resolve_paths(paths, deps, accept: accept) do |uri|
357
- @links << load(uri).uri
385
+ @to_link << to_load(uri)
358
386
  end
359
387
  end
360
388
 
361
- def resolve_paths(paths, deps, options = {})
389
+ def resolve_paths(paths, deps, **kargs)
362
390
  @dependencies.merge(deps)
363
391
  paths.each do |subpath, stat|
364
392
  next if subpath == @filename || stat.directory?
365
- uri, deps = @environment.resolve(subpath, options.merge(compat: false))
393
+ uri, deps = @environment.resolve(subpath, **kargs)
366
394
  @dependencies.merge(deps)
367
- yield uri if uri
395
+ yield uri if uri && block_given?
368
396
  end
369
397
  end
370
398
 
@@ -384,19 +412,19 @@ module Sprockets
384
412
  end
385
413
  end
386
414
 
387
- def load(uri)
388
- asset = @environment.load(uri)
389
- @dependencies.merge(asset.metadata[:dependencies])
390
- asset
415
+ def to_load(uri)
416
+ @to_load << uri
417
+ uri
391
418
  end
392
419
 
393
- def resolve(path, options = {})
420
+ def resolve(path, **kargs)
394
421
  # Prevent absolute paths in directives
395
422
  if @environment.absolute_path?(path)
396
423
  raise FileOutsidePaths, "can't require absolute file: #{path}"
397
424
  end
398
425
 
399
- uri, deps = @environment.resolve!(path, options.merge(base_path: @dirname))
426
+ kargs[:base_path] = @dirname
427
+ uri, deps = @environment.resolve!(path, **kargs)
400
428
  @dependencies.merge(deps)
401
429
  uri
402
430
  end
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
1
2
  require 'sprockets/autoload'
2
3
 
3
4
  module Sprockets
4
5
  # Processor engine class for the Eco compiler. Depends on the `eco` gem.
5
6
  #
6
- # For more infomation see:
7
+ # For more information see:
7
8
  #
8
9
  # https://github.com/sstephenson/ruby-eco
9
10
  # https://github.com/sstephenson/eco
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
1
2
  require 'sprockets/autoload'
2
3
 
3
4
  module Sprockets
4
5
  # Processor engine class for the EJS compiler. Depends on the `ejs` gem.
5
6
  #
6
- # For more infomation see:
7
+ # For more information see:
7
8
  #
8
9
  # https://github.com/sstephenson/ruby-ejs
9
10
  #
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'base64'
2
3
  require 'stringio'
3
4
  require 'zlib'
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  require 'sprockets/base'
2
3
  require 'sprockets/cache/memory_store'
3
4
  require 'sprockets/cached_environment'
4
5
 
5
6
  module Sprockets
6
7
  class Environment < Base
7
- # `Environment` should initialized with your application's root
8
+ # `Environment` should be initialized with your application's root
8
9
  # directory. This should be the same as your Rails or Rack root.
9
10
  #
10
11
  # env = Environment.new(Rails.root)
@@ -18,7 +19,7 @@ module Sprockets
18
19
 
19
20
  # Returns a cached version of the environment.
20
21
  #
21
- # All its file system calls are cached which makes `cached` much
22
+ # All of its file system calls are cached which makes `cached` much
22
23
  # faster. This behavior is ideal in production since the file
23
24
  # system only changes between deploys.
24
25
  def cached
@@ -26,8 +27,12 @@ module Sprockets
26
27
  end
27
28
  alias_method :index, :cached
28
29
 
29
- def find_asset(*args)
30
- cached.find_asset(*args)
30
+ def find_asset(*args, **options)
31
+ cached.find_asset(*args, **options)
32
+ end
33
+
34
+ def find_asset!(*args)
35
+ cached.find_asset!(*args)
31
36
  end
32
37
 
33
38
  def find_all_linked_assets(*args, &block)