sprockets 3.0.1 → 3.7.5

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 (52) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +308 -0
  3. data/README.md +49 -187
  4. data/bin/sprockets +1 -0
  5. data/lib/sprockets/asset.rb +3 -2
  6. data/lib/sprockets/base.rb +13 -2
  7. data/lib/sprockets/bundle.rb +5 -1
  8. data/lib/sprockets/cache/file_store.rb +7 -4
  9. data/lib/sprockets/cache.rb +6 -4
  10. data/lib/sprockets/closure_compressor.rb +5 -11
  11. data/lib/sprockets/coffee_script_processor.rb +2 -2
  12. data/lib/sprockets/coffee_script_template.rb +12 -1
  13. data/lib/sprockets/compressing.rb +20 -0
  14. data/lib/sprockets/dependencies.rb +8 -8
  15. data/lib/sprockets/deprecation.rb +90 -0
  16. data/lib/sprockets/digest_utils.rb +81 -57
  17. data/lib/sprockets/directive_processor.rb +2 -0
  18. data/lib/sprockets/eco_processor.rb +2 -2
  19. data/lib/sprockets/eco_template.rb +12 -1
  20. data/lib/sprockets/ejs_processor.rb +2 -2
  21. data/lib/sprockets/ejs_template.rb +12 -1
  22. data/lib/sprockets/encoding_utils.rb +7 -4
  23. data/lib/sprockets/engines.rb +11 -0
  24. data/lib/sprockets/erb_processor.rb +13 -1
  25. data/lib/sprockets/erb_template.rb +6 -1
  26. data/lib/sprockets/errors.rb +0 -1
  27. data/lib/sprockets/http_utils.rb +3 -1
  28. data/lib/sprockets/legacy.rb +20 -12
  29. data/lib/sprockets/legacy_proc_processor.rb +1 -1
  30. data/lib/sprockets/legacy_tilt_processor.rb +2 -2
  31. data/lib/sprockets/loader.rb +208 -59
  32. data/lib/sprockets/manifest.rb +57 -6
  33. data/lib/sprockets/mime.rb +26 -6
  34. data/lib/sprockets/path_utils.rb +20 -15
  35. data/lib/sprockets/processing.rb +10 -0
  36. data/lib/sprockets/processor_utils.rb +77 -0
  37. data/lib/sprockets/resolve.rb +10 -7
  38. data/lib/sprockets/sass_cache_store.rb +6 -1
  39. data/lib/sprockets/sass_compressor.rb +9 -17
  40. data/lib/sprockets/sass_processor.rb +16 -9
  41. data/lib/sprockets/sass_template.rb +14 -2
  42. data/lib/sprockets/server.rb +34 -14
  43. data/lib/sprockets/uglifier_compressor.rb +6 -13
  44. data/lib/sprockets/unloaded_asset.rb +137 -0
  45. data/lib/sprockets/uri_tar.rb +98 -0
  46. data/lib/sprockets/uri_utils.rb +14 -11
  47. data/lib/sprockets/utils/gzip.rb +67 -0
  48. data/lib/sprockets/utils.rb +36 -18
  49. data/lib/sprockets/version.rb +1 -1
  50. data/lib/sprockets/yui_compressor.rb +4 -14
  51. data/lib/sprockets.rb +21 -11
  52. metadata +49 -11
@@ -60,7 +60,7 @@ module Sprockets
60
60
  # cache - A compatible backend cache store instance.
61
61
  def initialize(cache = nil, logger = self.class.default_logger)
62
62
  @cache_wrapper = get_cache_wrapper(cache)
63
- @fetch_cache = Cache::MemoryStore.new(4096)
63
+ @fetch_cache = Cache::MemoryStore.new(1024)
64
64
  @logger = logger
65
65
  end
66
66
 
@@ -97,7 +97,7 @@ module Sprockets
97
97
  # Public: Low level API to retrieve item directly from the backend cache
98
98
  # store.
99
99
  #
100
- # This API may be used publicaly, but may have undefined behavior
100
+ # This API may be used publicly, but may have undefined behavior
101
101
  # depending on the backend store being used. Prefer the
102
102
  # Cache#fetch API over using this.
103
103
  #
@@ -120,7 +120,7 @@ module Sprockets
120
120
 
121
121
  # Public: Low level API to set item directly to the backend cache store.
122
122
  #
123
- # This API may be used publicaly, but may have undefined behavior
123
+ # This API may be used publicly, but may have undefined behavior
124
124
  # depending on the backend store being used. Prefer the
125
125
  # Cache#fetch API over using this.
126
126
  #
@@ -153,7 +153,9 @@ module Sprockets
153
153
  #
154
154
  # Returns a String with a length less than 250 characters.
155
155
  def expand_key(key)
156
- "sprockets/v#{VERSION}/#{DigestUtils.pack_urlsafe_base64digest(DigestUtils.digest(key))}"
156
+ digest_key = DigestUtils.pack_urlsafe_base64digest(DigestUtils.digest(key))
157
+ namespace = digest_key[0, 2]
158
+ "sprockets/v#{VERSION}/#{namespace}/#{digest_key}"
157
159
  end
158
160
 
159
161
  PEEK_SIZE = 100
@@ -1,4 +1,5 @@
1
1
  require 'sprockets/autoload'
2
+ require 'sprockets/digest_utils'
2
3
 
3
4
  module Sprockets
4
5
  # Public: Closure Compiler minifier.
@@ -34,20 +35,13 @@ module Sprockets
34
35
  attr_reader :cache_key
35
36
 
36
37
  def initialize(options = {})
37
- @compiler = Autoload::Closure::Compiler.new(options)
38
- @cache_key = [
39
- self.class.name,
40
- Autoload::Closure::VERSION,
41
- Autoload::Closure::COMPILER_VERSION,
42
- VERSION,
43
- options
44
- ].freeze
38
+ @options = options
39
+ @cache_key = "#{self.class.name}:#{Autoload::Closure::VERSION}:#{Autoload::Closure::COMPILER_VERSION}:#{VERSION}:#{DigestUtils.digest(options)}".freeze
45
40
  end
46
41
 
47
42
  def call(input)
48
- input[:cache].fetch(@cache_key + [input[:data]]) do
49
- @compiler.compile(input[:data])
50
- end
43
+ @compiler ||= Autoload::Closure::Compiler.new(@options)
44
+ @compiler.compile(input[:data])
51
45
  end
52
46
  end
53
47
  end
@@ -12,12 +12,12 @@ module Sprockets
12
12
  VERSION = '1'
13
13
 
14
14
  def self.cache_key
15
- @cache_key ||= [name, Autoload::CoffeeScript::Source.version, VERSION].freeze
15
+ @cache_key ||= "#{name}:#{Autoload::CoffeeScript::Source.version}:#{VERSION}".freeze
16
16
  end
17
17
 
18
18
  def self.call(input)
19
19
  data = input[:data]
20
- input[:cache].fetch(self.cache_key + [data]) do
20
+ input[:cache].fetch([self.cache_key, data]) do
21
21
  Autoload::CoffeeScript.compile(data)
22
22
  end
23
23
  end
@@ -2,5 +2,16 @@ require 'sprockets/coffee_script_processor'
2
2
 
3
3
  module Sprockets
4
4
  # Deprecated
5
- CoffeeScriptTemplate = CoffeeScriptProcessor
5
+ module CoffeeScriptTemplate
6
+ VERSION = CoffeeScriptProcessor::VERSION
7
+
8
+ def self.cache_key
9
+ CoffeeScriptProcessor.cache_key
10
+ end
11
+
12
+ def self.call(*args)
13
+ Deprecation.new.warn "CoffeeScriptTemplate is deprecated please use CoffeeScriptProcessor instead"
14
+ CoffeeScriptProcessor.call(*args)
15
+ end
16
+ end
6
17
  end
@@ -70,5 +70,25 @@ module Sprockets
70
70
 
71
71
  register_bundle_processor 'application/javascript', klass
72
72
  end
73
+
74
+ # Public: Checks if Gzip is enabled.
75
+ def gzip?
76
+ config[:gzip_enabled]
77
+ end
78
+
79
+ # Public: Checks if Gzip is disabled.
80
+ def skip_gzip?
81
+ !gzip?
82
+ end
83
+
84
+ # Public: Enable or disable the creation of Gzip files.
85
+ #
86
+ # Defaults to true.
87
+ #
88
+ # environment.gzip = false
89
+ #
90
+ def gzip=(gzip)
91
+ self.config = config.merge(gzip_enabled: gzip).freeze
92
+ end
73
93
  end
74
94
  end
@@ -51,18 +51,18 @@ module Sprockets
51
51
  end
52
52
  alias_method :depend_on, :add_dependency
53
53
 
54
- # Internal: Resolve set of dependency URIs.
55
- #
56
- # Returns Array of resolved Objects.
57
- def resolve_dependencies(uris)
58
- uris.map { |uri| resolve_dependency(uri) }
59
- end
60
-
61
54
  # Internal: Resolve dependency URIs.
62
55
  #
63
56
  # Returns resolved Object.
64
57
  def resolve_dependency(str)
65
- scheme = str[/([^:]+)/, 1]
58
+ # Optimize for the most common scheme to
59
+ # save 22k allocations on an average Spree app.
60
+ scheme = if str.start_with?('file-digest:'.freeze)
61
+ 'file-digest'.freeze
62
+ else
63
+ str[/([^:]+)/, 1]
64
+ end
65
+
66
66
  if resolver = config[:dependency_resolvers][scheme]
67
67
  resolver.call(self, str)
68
68
  else
@@ -0,0 +1,90 @@
1
+ module Sprockets
2
+ class Deprecation
3
+ THREAD_LOCAL__SILENCE_KEY = "_sprockets_deprecation_silence".freeze
4
+ DEFAULT_BEHAVIORS = {
5
+ raise: ->(message, callstack) {
6
+ e = DeprecationException.new(message)
7
+ e.set_backtrace(callstack.map(&:to_s))
8
+ raise e
9
+ },
10
+
11
+ stderr: ->(message, callstack) {
12
+ $stderr.puts(message)
13
+ },
14
+ }
15
+
16
+ attr_reader :callstack
17
+
18
+ def self.silence(&block)
19
+ Thread.current[THREAD_LOCAL__SILENCE_KEY] = true
20
+ block.call
21
+ ensure
22
+ Thread.current[THREAD_LOCAL__SILENCE_KEY] = false
23
+ end
24
+
25
+ def initialize(callstack = nil)
26
+ @callstack = callstack || caller(2)
27
+ end
28
+
29
+ def warn(message)
30
+ return if Thread.current[THREAD_LOCAL__SILENCE_KEY]
31
+ deprecation_message(message).tap do |m|
32
+ behavior.each { |b| b.call(m, callstack) }
33
+ end
34
+ end
35
+
36
+ private
37
+ def behavior
38
+ @behavior ||= [DEFAULT_BEHAVIORS[:stderr]]
39
+ end
40
+
41
+ def behavior=(behavior)
42
+ @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || b }
43
+ end
44
+
45
+ def deprecation_message(message = nil)
46
+ message ||= "You are using deprecated behavior which will be removed from the next major or minor release."
47
+ "DEPRECATION WARNING: #{message} #{ deprecation_caller_message }"
48
+ end
49
+
50
+ def deprecation_caller_message
51
+ file, line, method = extract_callstack
52
+ if file
53
+ if line && method
54
+ "(called from #{method} at #{file}:#{line})"
55
+ else
56
+ "(called from #{file}:#{line})"
57
+ end
58
+ end
59
+ end
60
+
61
+ SPROCKETS_GEM_ROOT = File.expand_path("../../../../..", __FILE__) + "/"
62
+
63
+ def ignored_callstack(path)
64
+ path.start_with?(SPROCKETS_GEM_ROOT) || path.start_with?(RbConfig::CONFIG['rubylibdir'])
65
+ end
66
+
67
+ def extract_callstack
68
+ return _extract_callstack if callstack.first.is_a? String
69
+
70
+ offending_line = callstack.find { |frame|
71
+ frame.absolute_path && !ignored_callstack(frame.absolute_path)
72
+ } || callstack.first
73
+
74
+ [offending_line.path, offending_line.lineno, offending_line.label]
75
+ end
76
+
77
+ def _extract_callstack
78
+ offending_line = callstack.find { |line| !ignored_callstack(line) } || callstack.first
79
+
80
+ if offending_line
81
+ if md = offending_line.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
82
+ md.captures
83
+ else
84
+ offending_line
85
+ end
86
+ end
87
+ end
88
+ end
89
+ private_constant :Deprecation
90
+ end
@@ -34,6 +34,56 @@ module Sprockets
34
34
  DIGEST_SIZES[bytes.bytesize]
35
35
  end
36
36
 
37
+ ADD_VALUE_TO_DIGEST = {
38
+ String => ->(val, digest) { digest << val },
39
+ FalseClass => ->(val, digest) { digest << 'FalseClass'.freeze },
40
+ TrueClass => ->(val, digest) { digest << 'TrueClass'.freeze },
41
+ NilClass => ->(val, digest) { digest << 'NilClass'.freeze },
42
+
43
+ Symbol => ->(val, digest) {
44
+ digest << 'Symbol'.freeze
45
+ digest << val.to_s
46
+ },
47
+ Integer => ->(val, digest) {
48
+ digest << 'Integer'.freeze
49
+ digest << val.to_s
50
+ },
51
+ Array => ->(val, digest) {
52
+ digest << 'Array'.freeze
53
+ val.each do |element|
54
+ ADD_VALUE_TO_DIGEST[element.class].call(element, digest)
55
+ end
56
+ },
57
+ Hash => ->(val, digest) {
58
+ digest << 'Hash'.freeze
59
+ val.sort.each do |array|
60
+ ADD_VALUE_TO_DIGEST[Array].call(array, digest)
61
+ end
62
+ },
63
+ Set => ->(val, digest) {
64
+ digest << 'Set'.freeze
65
+ ADD_VALUE_TO_DIGEST[Array].call(val.to_a, digest)
66
+ },
67
+ Encoding => ->(val, digest) {
68
+ digest << 'Encoding'.freeze
69
+ 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
+ }
81
+ end
82
+ ADD_VALUE_TO_DIGEST.default_proc = ->(_, val) {
83
+ raise TypeError, "couldn't digest #{ val }"
84
+ }
85
+ private_constant :ADD_VALUE_TO_DIGEST
86
+
37
87
  # Internal: Generate a hexdigest for a nested JSON serializable object.
38
88
  #
39
89
  # This is used for generating cache keys, so its pretty important its
@@ -44,46 +94,8 @@ module Sprockets
44
94
  # Returns a String digest of the object.
45
95
  def digest(obj)
46
96
  digest = digest_class.new
47
- queue = [obj]
48
-
49
- while queue.length > 0
50
- obj = queue.shift
51
- klass = obj.class
52
-
53
- if klass == String
54
- digest << obj
55
- elsif klass == Symbol
56
- digest << 'Symbol'
57
- digest << obj.to_s
58
- elsif klass == Fixnum
59
- digest << 'Fixnum'
60
- digest << obj.to_s
61
- elsif klass == Bignum
62
- digest << 'Bignum'
63
- digest << obj.to_s
64
- elsif klass == TrueClass
65
- digest << 'TrueClass'
66
- elsif klass == FalseClass
67
- digest << 'FalseClass'
68
- elsif klass == NilClass
69
- digest << 'NilClass'
70
- elsif klass == Array
71
- digest << 'Array'
72
- queue.concat(obj)
73
- elsif klass == Hash
74
- digest << 'Hash'
75
- queue.concat(obj.sort)
76
- elsif klass == Set
77
- digest << 'Set'
78
- queue.concat(obj.to_a)
79
- elsif klass == Encoding
80
- digest << 'Encoding'
81
- digest << obj.name
82
- else
83
- raise TypeError, "couldn't digest #{klass}"
84
- end
85
- end
86
97
 
98
+ ADD_VALUE_TO_DIGEST[obj.class].call(obj, digest)
87
99
  digest.digest
88
100
  end
89
101
 
@@ -96,6 +108,15 @@ module Sprockets
96
108
  bin.unpack('H*').first
97
109
  end
98
110
 
111
+ # Internal: Unpack a hex encoded digest string into binary bytes.
112
+ #
113
+ # hex - String hex
114
+ #
115
+ # Returns binary String.
116
+ def unpack_hexdigest(hex)
117
+ [hex].pack('H*')
118
+ end
119
+
99
120
  # Internal: Pack a binary digest to a base64 encoded string.
100
121
  #
101
122
  # bin - String bytes
@@ -117,25 +138,20 @@ module Sprockets
117
138
  str
118
139
  end
119
140
 
120
- # Internal: Maps digest class to the named information hash algorithm name.
121
- #
122
- # http://www.iana.org/assignments/named-information/named-information.xhtml
123
- NI_HASH_ALGORITHMS = {
124
- Digest::SHA256 => 'sha-256'.freeze,
125
- Digest::SHA384 => 'sha-384'.freeze,
126
- Digest::SHA512 => 'sha-512'.freeze
141
+ # Internal: Maps digest class to the CSP hash algorithm name.
142
+ HASH_ALGORITHMS = {
143
+ Digest::SHA256 => 'sha256'.freeze,
144
+ Digest::SHA384 => 'sha384'.freeze,
145
+ Digest::SHA512 => 'sha512'.freeze
127
146
  }
128
147
 
129
- # Internal: Generate a "named information" URI for use in the `integrity`
130
- # attribute of an asset tag as per the subresource integrity specification.
148
+ # Public: Generate hash for use in the `integrity` attribute of an asset tag
149
+ # as per the subresource integrity specification.
131
150
  #
132
- # digest - The String byte digest of the asset content.
133
- # content_type - The content-type the asset will be served with. This *must*
134
- # be accurate if provided. Otherwise, subresource integrity
135
- # will block the loading of the asset.
151
+ # digest - The String byte digest of the asset content.
136
152
  #
137
153
  # Returns a String or nil if hash algorithm is incompatible.
138
- def integrity_uri(digest, content_type = nil)
154
+ def integrity_uri(digest)
139
155
  case digest
140
156
  when Digest::Base
141
157
  digest_class = digest.class
@@ -146,11 +162,19 @@ module Sprockets
146
162
  raise TypeError, "unknown digest: #{digest.inspect}"
147
163
  end
148
164
 
149
- if hash_name = NI_HASH_ALGORITHMS[digest_class]
150
- uri = "ni:///#{hash_name};#{pack_urlsafe_base64digest(digest)}"
151
- uri << "?ct=#{content_type}" if content_type
152
- uri
165
+ if hash_name = HASH_ALGORITHMS[digest_class]
166
+ "#{hash_name}-#{pack_base64digest(digest)}"
153
167
  end
154
168
  end
169
+
170
+ # Public: Generate hash for use in the `integrity` attribute of an asset tag
171
+ # as per the subresource integrity specification.
172
+ #
173
+ # digest - The String hexbyte digest of the asset content.
174
+ #
175
+ # Returns a String or nil if hash algorithm is incompatible.
176
+ def hexdigest_integrity_uri(hexdigest)
177
+ integrity_uri(unpack_hexdigest(hexdigest))
178
+ end
155
179
  end
156
180
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: false
2
+
1
3
  require 'set'
2
4
  require 'shellwords'
3
5
 
@@ -12,7 +12,7 @@ module Sprockets
12
12
  VERSION = '1'
13
13
 
14
14
  def self.cache_key
15
- @cache_key ||= [name, Autoload::Eco::Source::VERSION, VERSION].freeze
15
+ @cache_key ||= "#{name}:#{Autoload::Eco::Source::VERSION}:#{VERSION}".freeze
16
16
  end
17
17
 
18
18
  # Compile template data with Eco compiler.
@@ -24,7 +24,7 @@ module Sprockets
24
24
  #
25
25
  def self.call(input)
26
26
  data = input[:data]
27
- input[:cache].fetch(cache_key + [data]) do
27
+ input[:cache].fetch([cache_key, data]) do
28
28
  Autoload::Eco.compile(data)
29
29
  end
30
30
  end
@@ -2,5 +2,16 @@ require 'sprockets/eco_processor'
2
2
 
3
3
  module Sprockets
4
4
  # Deprecated
5
- EcoTemplate = EcoProcessor
5
+ module EcoTemplate
6
+ VERSION = EcoProcessor::VERSION
7
+
8
+ def self.cache_key
9
+ EcoProcessor.cache_key
10
+ end
11
+
12
+ def self.call(*args)
13
+ Deprecation.new.warn "EcoTemplate is deprecated please use EcoProcessor instead"
14
+ EcoProcessor.call(*args)
15
+ end
16
+ end
6
17
  end
@@ -11,7 +11,7 @@ module Sprockets
11
11
  VERSION = '1'
12
12
 
13
13
  def self.cache_key
14
- @cache_key ||= [name, VERSION].freeze
14
+ @cache_key ||= "#{name}:#{VERSION}".freeze
15
15
  end
16
16
 
17
17
  # Compile template data with EJS compiler.
@@ -23,7 +23,7 @@ module Sprockets
23
23
  #
24
24
  def self.call(input)
25
25
  data = input[:data]
26
- input[:cache].fetch(cache_key + [data]) do
26
+ input[:cache].fetch([cache_key, data]) do
27
27
  Autoload::EJS.compile(data)
28
28
  end
29
29
  end
@@ -2,5 +2,16 @@ require 'sprockets/ejs_processor'
2
2
 
3
3
  module Sprockets
4
4
  # Deprecated
5
- EjsTemplate = EjsProcessor
5
+ module EjsTemplate
6
+ VERSION = EjsProcessor::VERSION
7
+
8
+ def self.cache_key
9
+ EjsProcessor.cache_key
10
+ end
11
+
12
+ def self.call(*args)
13
+ Deprecation.new.warn "EjsTemplate is deprecated please use EjsProcessor instead"
14
+ EjsProcessor.call(*args)
15
+ end
16
+ end
6
17
  end
@@ -104,7 +104,7 @@ module Sprockets
104
104
  charlock_detect(str)
105
105
  end
106
106
 
107
- # Fallback to UTF-8
107
+ # Fallback to environment's external encoding
108
108
  if str.encoding == Encoding::BINARY
109
109
  str.force_encoding(Encoding.default_external)
110
110
  end
@@ -233,7 +233,10 @@ module Sprockets
233
233
  nil
234
234
  end
235
235
 
236
- # Public: Detect charset from HTML document. Defaults to ISO-8859-1.
236
+ # Public: Detect charset from HTML document.
237
+ #
238
+ # Attempts to parse any Unicode BOM otherwise attempt Charlock detection
239
+ # and finally falls back to the environment's external encoding.
237
240
  #
238
241
  # str - String.
239
242
  #
@@ -246,9 +249,9 @@ module Sprockets
246
249
  charlock_detect(str)
247
250
  end
248
251
 
249
- # Fallback to ISO-8859-1
252
+ # Fallback to environment's external encoding
250
253
  if str.encoding == Encoding::BINARY
251
- str.force_encoding(Encoding::ISO_8859_1)
254
+ str.force_encoding(Encoding.default_external)
252
255
  end
253
256
 
254
257
  str
@@ -51,6 +51,17 @@ module Sprockets
51
51
  # environment.register_engine '.coffee', CoffeeScriptProcessor
52
52
  #
53
53
  def register_engine(ext, klass, options = {})
54
+ unless options[:silence_deprecation]
55
+ msg = <<-MSG
56
+ Sprockets method `register_engine` is deprecated.
57
+ Please register a mime type using `register_mime_type` then
58
+ use `register_compressor` or `register_transformer`.
59
+ https://github.com/rails/sprockets/blob/master/guides/extending_sprockets.md#supporting-all-versions-of-sprockets-in-processors
60
+ MSG
61
+
62
+ Deprecation.new([caller.first]).warn(msg)
63
+ end
64
+
54
65
  ext = Sprockets::Utils.normalize_extension(ext)
55
66
 
56
67
  self.computed_config = {}
@@ -18,7 +18,12 @@ module Sprockets
18
18
  end
19
19
 
20
20
  def call(input)
21
- engine = ::ERB.new(input[:data], nil, '<>')
21
+ if keyword_constructor? # Ruby 2.6+
22
+ engine = ::ERB.new(input[:data], trim_mode: '<>')
23
+ else
24
+ engine = ::ERB.new(input[:data], nil, '<>')
25
+ end
26
+
22
27
  context = input[:environment].context_class.new(input)
23
28
  klass = (class << context; self; end)
24
29
  klass.class_eval(&@block) if @block
@@ -26,5 +31,12 @@ module Sprockets
26
31
  data = context._evaluate_template
27
32
  context.metadata.merge(data: data)
28
33
  end
34
+
35
+ private
36
+
37
+ def keyword_constructor?
38
+ return @keyword_constructor if defined? @keyword_constructor
39
+ @keyword_constructor = ::ERB.instance_method(:initialize).parameters.include?([:key, :trim_mode])
40
+ end
29
41
  end
30
42
  end
@@ -2,5 +2,10 @@ require 'sprockets/erb_processor'
2
2
 
3
3
  module Sprockets
4
4
  # Deprecated
5
- ERBTemplate = ERBProcessor
5
+ class ERBTemplate < ERBProcessor
6
+ def call(*args)
7
+ Deprecation.new.warn "ERBTemplate is deprecated please use ERBProcessor instead"
8
+ super
9
+ end
10
+ end
6
11
  end
@@ -8,5 +8,4 @@ module Sprockets
8
8
  class ConversionError < NotFound; end
9
9
  class FileNotFound < NotFound; end
10
10
  class FileOutsidePaths < NotFound; end
11
- class VersionNotFound < NotFound; end
12
11
  end
@@ -76,7 +76,9 @@ module Sprockets
76
76
  end
77
77
  end
78
78
 
79
- matches.sort_by { |match, quality| -quality }.map { |match, quality| match }
79
+ matches.sort_by! { |match, quality| -quality }
80
+ matches.map! { |match, quality| match }
81
+ matches
80
82
  end
81
83
 
82
84
  # Internal: Find the best qvalue match from an Array of available options.
@@ -128,6 +128,12 @@ module Sprockets
128
128
  cache.set(key, value)
129
129
  end
130
130
 
131
+ def normalize_logical_path(path)
132
+ dirname, basename = File.split(path)
133
+ path = dirname if basename == 'index'
134
+ path
135
+ end
136
+
131
137
  private
132
138
  # Deprecated: Seriously.
133
139
  def matches_filter(filters, logical_path, filename)
@@ -148,18 +154,10 @@ module Sprockets
148
154
  end
149
155
  end
150
156
 
151
- # URI.unescape is deprecated on 1.9. We need to use URI::Parser
152
- # if its available.
153
- if defined? URI::DEFAULT_PARSER
154
- def unescape(str)
155
- str = URI::DEFAULT_PARSER.unescape(str)
156
- str.force_encoding(Encoding.default_internal) if Encoding.default_internal
157
- str
158
- end
159
- else
160
- def unescape(str)
161
- URI.unescape(str)
162
- end
157
+ def unescape(str)
158
+ str = URIUtils::URI_PARSER.unescape(str)
159
+ str.force_encoding(Encoding.default_internal) if Encoding.default_internal
160
+ str
163
161
  end
164
162
  end
165
163
 
@@ -297,6 +295,16 @@ module Sprockets
297
295
  str !~ /\*|\*\*|\?|\[|\]|\{|\}/
298
296
  end
299
297
 
298
+ def self.compute_alias_logical_path(path)
299
+ dirname, basename = File.split(path)
300
+ extname = File.extname(basename)
301
+ if File.basename(basename, extname) == 'index'
302
+ "#{dirname}#{extname}"
303
+ else
304
+ nil
305
+ end
306
+ end
307
+
300
308
  # Deprecated: Filter logical paths in environment. Useful for selecting what
301
309
  # files you want to compile.
302
310
  #
@@ -29,7 +29,7 @@ module Sprockets
29
29
  def call(input)
30
30
  context = input[:environment].context_class.new(input)
31
31
  data = @proc.call(context, input[:data])
32
- context.metadata.merge(data: data)
32
+ context.metadata.merge(data: data.to_str)
33
33
  end
34
34
  end
35
35
  end