sprockets 3.7.3 → 4.2.1

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 +73 -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 -38
  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 +33 -32
  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 +91 -69
  54. data/lib/sprockets/manifest.rb +67 -64
  55. data/lib/sprockets/manifest_utils.rb +9 -6
  56. data/lib/sprockets/mime.rb +8 -62
  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 +63 -40
  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 -12
  81. data/lib/sprockets/utils/gzip.rb +46 -14
  82. data/lib/sprockets/utils.rb +64 -90
  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 +138 -46
  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,5 +1,4 @@
1
- # frozen_string_literal: false
2
-
1
+ # frozen_string_literal: true
3
2
  require 'set'
4
3
  require 'shellwords'
5
4
 
@@ -36,8 +35,6 @@ module Sprockets
36
35
  # env.register_processor('text/css', MyProcessor)
37
36
  #
38
37
  class DirectiveProcessor
39
- VERSION = '1'
40
-
41
38
  # Directives are denoted by a `=` followed by the name, then
42
39
  # argument list.
43
40
  #
@@ -52,18 +49,16 @@ module Sprockets
52
49
  /x
53
50
 
54
51
  def self.instance
55
- @instance ||= new(
56
- # Deprecated: Default to C and Ruby comment styles
57
- comments: ["//", ["/*", "*/"]] + ["#", ["###", "###"]]
58
- )
52
+ # Default to C comment styles
53
+ @instance ||= new(comments: ["//", ["/*", "*/"]])
59
54
  end
60
55
 
61
56
  def self.call(input)
62
57
  instance.call(input)
63
58
  end
64
59
 
65
- def initialize(options = {})
66
- @header_pattern = compile_header_pattern(Array(options[:comments]))
60
+ def initialize(comments: [])
61
+ @header_pattern = compile_header_pattern(Array(comments))
67
62
  end
68
63
 
69
64
  def call(input)
@@ -75,20 +70,28 @@ module Sprockets
75
70
  @uri = input[:uri]
76
71
  @filename = input[:filename]
77
72
  @dirname = File.dirname(@filename)
78
- @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)
79
76
  @required = Set.new(input[:metadata][:required])
80
77
  @stubbed = Set.new(input[:metadata][:stubbed])
81
78
  @links = Set.new(input[:metadata][:links])
82
79
  @dependencies = Set.new(input[:metadata][:dependencies])
80
+ @to_link = Set.new
81
+ @to_load = Set.new
83
82
 
84
83
  data, directives = process_source(input[:data])
85
84
  process_directives(directives)
86
85
 
87
- { data: data,
88
- required: @required,
89
- stubbed: @stubbed,
90
- links: @links,
91
- 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
+ }
92
95
  end
93
96
 
94
97
  protected
@@ -118,9 +121,9 @@ module Sprockets
118
121
 
119
122
  header, directives = extract_directives(header)
120
123
 
121
- data = ""
124
+ data = +""
122
125
  data.force_encoding(body.encoding)
123
- data << header << "\n" unless header.empty?
126
+ data << header unless header.empty?
124
127
  data << body
125
128
  # Ensure body ends in a new line
126
129
  data << "\n" if data.length > 0 && data[-1] != "\n"
@@ -136,7 +139,7 @@ module Sprockets
136
139
  # [[1, "require", "foo"], [2, "require", "bar"]]
137
140
  #
138
141
  def extract_directives(header)
139
- processed_header = ""
142
+ processed_header = +""
140
143
  directives = []
141
144
 
142
145
  header.lines.each_with_index do |line, index|
@@ -151,7 +154,11 @@ module Sprockets
151
154
  processed_header << line
152
155
  end
153
156
 
154
- 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
155
162
  end
156
163
 
157
164
  # Gathers comment directives in the source and processes them.
@@ -164,7 +171,7 @@ module Sprockets
164
171
  # `process_require_glob_directive`.
165
172
  #
166
173
  # class DirectiveProcessor < Sprockets::DirectiveProcessor
167
- # def process_require_glob_directive
174
+ # def process_require_glob_directive(glob)
168
175
  # Dir["#{dirname}/#{glob}"].sort.each do |filename|
169
176
  # require(filename)
170
177
  # end
@@ -189,7 +196,7 @@ module Sprockets
189
196
 
190
197
  # The `require` directive functions similar to Ruby's own `require`.
191
198
  # It provides a way to declare a dependency on a file in your path
192
- # and ensures its only loaded once before the source file.
199
+ # and ensures it's only loaded once before the source file.
193
200
  #
194
201
  # `require` works with files in the environment path:
195
202
  #
@@ -267,15 +274,33 @@ module Sprockets
267
274
  # it.
268
275
  #
269
276
  # This is used for caching purposes. Any changes that would
270
- # invalid the asset dependency will invalidate the cache our the
271
- # source file.
277
+ # invalidate the asset dependency will invalidate the cache of
278
+ # the source file.
272
279
  #
273
280
  # Unlike `depend_on`, the path must be a requirable asset.
274
281
  #
275
282
  # //= depend_on_asset "bar.js"
276
283
  #
277
284
  def process_depend_on_asset_directive(path)
278
- 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)
279
304
  end
280
305
 
281
306
  # Allows dependency to be excluded from the asset bundle.
@@ -299,7 +324,8 @@ module Sprockets
299
324
  # /*= link "logo.png" */
300
325
  #
301
326
  def process_link_directive(path)
302
- @links << load(resolve(path)).uri
327
+ uri = to_load(resolve(path))
328
+ @to_link << uri
303
329
  end
304
330
 
305
331
  # `link_directory` links all the files inside a single
@@ -309,7 +335,7 @@ module Sprockets
309
335
  # //= link_directory "./fonts"
310
336
  #
311
337
  # Use caution when linking against JS or CSS assets. Include an explicit
312
- # extension or content type in these cases
338
+ # extension or content type in these cases.
313
339
  #
314
340
  # //= link_directory "./scripts" .js
315
341
  #
@@ -325,7 +351,7 @@ module Sprockets
325
351
  # //= link_tree "./images"
326
352
  #
327
353
  # Use caution when linking against JS or CSS assets. Include an explicit
328
- # extension or content type in these cases
354
+ # extension or content type in these cases.
329
355
  #
330
356
  # //= link_tree "./styles" .css
331
357
  #
@@ -356,17 +382,17 @@ module Sprockets
356
382
 
357
383
  def link_paths(paths, deps, accept)
358
384
  resolve_paths(paths, deps, accept: accept) do |uri|
359
- @links << load(uri).uri
385
+ @to_link << to_load(uri)
360
386
  end
361
387
  end
362
388
 
363
- def resolve_paths(paths, deps, options = {})
389
+ def resolve_paths(paths, deps, **kargs)
364
390
  @dependencies.merge(deps)
365
391
  paths.each do |subpath, stat|
366
392
  next if subpath == @filename || stat.directory?
367
- uri, deps = @environment.resolve(subpath, options.merge(compat: false))
393
+ uri, deps = @environment.resolve(subpath, **kargs)
368
394
  @dependencies.merge(deps)
369
- yield uri if uri
395
+ yield uri if uri && block_given?
370
396
  end
371
397
  end
372
398
 
@@ -386,19 +412,19 @@ module Sprockets
386
412
  end
387
413
  end
388
414
 
389
- def load(uri)
390
- asset = @environment.load(uri)
391
- @dependencies.merge(asset.metadata[:dependencies])
392
- asset
415
+ def to_load(uri)
416
+ @to_load << uri
417
+ uri
393
418
  end
394
419
 
395
- def resolve(path, options = {})
420
+ def resolve(path, **kargs)
396
421
  # Prevent absolute paths in directives
397
422
  if @environment.absolute_path?(path)
398
423
  raise FileOutsidePaths, "can't require absolute file: #{path}"
399
424
  end
400
425
 
401
- uri, deps = @environment.resolve!(path, options.merge(base_path: @dirname))
426
+ kargs[:base_path] = @dirname
427
+ uri, deps = @environment.resolve!(path, **kargs)
402
428
  @dependencies.merge(deps)
403
429
  uri
404
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)