sprockets 3.7.3 → 4.2.2

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 +77 -259
  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 +2 -2
  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 +19 -16
  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 +148 -45
  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,52 @@
1
+ # frozen_string_literal: true
2
+ require 'json'
3
+
4
+ module Sprockets
5
+ module Npm
6
+ # Internal: Override resolve_alternates to install package.json behavior.
7
+ #
8
+ # load_path - String environment path
9
+ # logical_path - String path relative to base
10
+ #
11
+ # Returns candidate filenames.
12
+ def resolve_alternates(load_path, logical_path)
13
+ candidates, deps = super
14
+
15
+ dirname = File.join(load_path, logical_path)
16
+
17
+ if directory?(dirname)
18
+ filename = File.join(dirname, 'package.json')
19
+
20
+ if self.file?(filename)
21
+ deps << build_file_digest_uri(filename)
22
+ read_package_directives(dirname, filename) do |path|
23
+ if file?(path)
24
+ candidates << path
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ return candidates, deps
31
+ end
32
+
33
+ # Internal: Read package.json's main and style directives.
34
+ #
35
+ # dirname - String path to component directory.
36
+ # filename - String path to package.json.
37
+ #
38
+ # Returns nothing.
39
+ def read_package_directives(dirname, filename)
40
+ package = JSON.parse(File.read(filename), create_additions: false)
41
+
42
+ case package['main']
43
+ when String
44
+ yield File.expand_path(package['main'], dirname)
45
+ when nil
46
+ yield File.expand_path('index.js', dirname)
47
+ end
48
+
49
+ yield File.expand_path(package['style'], dirname) if package['style']
50
+ end
51
+ end
52
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'set'
2
3
  require 'sprockets/path_utils'
3
4
  require 'sprockets/uri_utils'
@@ -41,7 +42,7 @@ module Sprockets
41
42
  #
42
43
  # Returns an Array of entry names and a Set of dependency URIs.
43
44
  def entries_with_dependencies(path)
44
- return entries(path), file_digest_dependency_set(path)
45
+ return entries(path), Set.new([build_file_digest_uri(path)])
45
46
  end
46
47
 
47
48
  # Internal: List directory filenames and associated Stats under a
@@ -53,16 +54,7 @@ module Sprockets
53
54
  #
54
55
  # Returns an Array of filenames and a Set of dependency URIs.
55
56
  def stat_directory_with_dependencies(dir)
56
- return stat_directory(dir).to_a, file_digest_dependency_set(dir)
57
- end
58
-
59
- # Internal: Returns a set of dependencies for a particular path.
60
- #
61
- # path - String directory path
62
- #
63
- # Returns a Set of dependency URIs.
64
- def file_digest_dependency_set(path)
65
- Set.new([build_file_digest_uri(path)])
57
+ return stat_directory(dir).to_a, Set.new([build_file_digest_uri(dir)])
66
58
  end
67
59
 
68
60
  # Internal: List directory filenames and associated Stats under an entire
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'sprockets/digest_utils'
2
3
  require 'sprockets/path_utils'
3
4
 
@@ -15,7 +16,7 @@ module Sprockets
15
16
  def stat_digest(path, stat)
16
17
  if stat.directory?
17
18
  # If its a directive, digest the list of filenames
18
- digest_class.digest(self.entries(path).join(','))
19
+ digest_class.digest(self.entries(path).join(','.freeze))
19
20
  elsif stat.file?
20
21
  # If its a file, digest the contents
21
22
  digest_class.file(path.to_s).digest
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Sprockets
2
3
  # Internal: File and path related utilities. Mixed into Environment.
3
4
  #
@@ -5,6 +6,7 @@ module Sprockets
5
6
  # when code actually wants to reference ::FileUtils.
6
7
  module PathUtils
7
8
  extend self
9
+ require 'pathname'
8
10
 
9
11
  # Public: Like `File.stat`.
10
12
  #
@@ -53,13 +55,14 @@ module Sprockets
53
55
  # Returns an empty `Array` if the directory does not exist.
54
56
  def entries(path)
55
57
  if File.directory?(path)
56
- entries = Dir.entries(path, :encoding => Encoding.default_internal)
58
+ entries = Dir.entries(path, encoding: Encoding.default_internal)
57
59
  entries.reject! { |entry|
58
60
  entry.start_with?(".".freeze) ||
59
61
  (entry.start_with?("#".freeze) && entry.end_with?("#".freeze)) ||
60
62
  entry.end_with?("~".freeze)
61
63
  }
62
64
  entries.sort!
65
+ entries
63
66
  else
64
67
  []
65
68
  end
@@ -71,8 +74,6 @@ module Sprockets
71
74
  #
72
75
  # Returns true if path is absolute, otherwise false.
73
76
  if File::ALT_SEPARATOR
74
- require 'pathname'
75
-
76
77
  # On Windows, ALT_SEPARATOR is \
77
78
  # Delegate to Pathname since the logic gets complex.
78
79
  def absolute_path?(path)
@@ -80,7 +81,7 @@ module Sprockets
80
81
  end
81
82
  else
82
83
  def absolute_path?(path)
83
- path[0] == File::SEPARATOR
84
+ path.start_with?(File::SEPARATOR)
84
85
  end
85
86
  end
86
87
 
@@ -97,7 +98,58 @@ module Sprockets
97
98
  #
98
99
  # Returns true if path is relative, otherwise false.
99
100
  def relative_path?(path)
100
- path =~ /^\.\.?($|#{SEPARATOR_PATTERN})/ ? true : false
101
+ path.match?(/^\.\.?($|#{SEPARATOR_PATTERN})/) ? true : false
102
+ end
103
+
104
+ # Public: Get relative path from `start` to `dest`.
105
+ #
106
+ # start - String start path (file or dir)
107
+ # dest - String destination path
108
+ #
109
+ # Returns relative String path from `start` to `dest`
110
+ def relative_path_from(start, dest)
111
+ start, dest = Pathname.new(start), Pathname.new(dest)
112
+ start = start.dirname unless start.directory?
113
+ dest.relative_path_from(start).to_s
114
+ end
115
+
116
+ # Public: Joins path to base path.
117
+ #
118
+ # base - Root path
119
+ # path - Extending path
120
+ #
121
+ # Example
122
+ #
123
+ # join('base/path/', '../file.js')
124
+ # # => 'base/file.js'
125
+ #
126
+ # Returns string path starting from base and ending at path
127
+ def join(base, path)
128
+ (Pathname.new(base) + path).to_s
129
+ end
130
+
131
+ # Public: Sets pipeline for path
132
+ #
133
+ # path - String path
134
+ # extensions - List of file extensions
135
+ # pipeline - Pipeline
136
+ #
137
+ # Examples
138
+ #
139
+ # set_pipeline('path/file.js.erb', config[:mime_exts], config[:pipeline_exts], :source)
140
+ # # => 'path/file.source.js.erb'
141
+ #
142
+ # set_pipeline('path/some.file.source.js.erb', config[:mime_exts], config[:pipeline_exts], :debug)
143
+ # # => 'path/some.file.debug.js.erb'
144
+ #
145
+ # Returns string path with pipeline parsed in
146
+ def set_pipeline(path, mime_exts, pipeline_exts, pipeline)
147
+ extension, _ = match_path_extname(path, mime_exts)
148
+ path.chomp!(extension)
149
+ pipeline_old, _ = match_path_extname(path, pipeline_exts)
150
+ path.chomp!(pipeline_old)
151
+
152
+ "#{path}.#{pipeline}#{extension}"
101
153
  end
102
154
 
103
155
  # Internal: Get relative path for root path and subpath.
@@ -109,8 +161,8 @@ module Sprockets
109
161
  # subpath is outside of path.
110
162
  def split_subpath(path, subpath)
111
163
  return "" if path == subpath
112
- path = File.join(path, '')
113
- if subpath.start_with?(path)
164
+ path = File.join(path, ''.freeze)
165
+ if subpath&.start_with?(path)
114
166
  subpath[path.length..-1]
115
167
  else
116
168
  nil
@@ -163,6 +215,34 @@ module Sprockets
163
215
  nil
164
216
  end
165
217
 
218
+ # Internal: Match paths in a directory against available extensions.
219
+ #
220
+ # path - String directory
221
+ # basename - String basename of target file
222
+ # extensions - Hash of String extnames to values
223
+ #
224
+ # Examples
225
+ #
226
+ # exts = { ".js" => "application/javascript" }
227
+ # find_matching_path_for_extensions("app/assets", "application", exts)
228
+ # # => ["app/assets/application.js", "application/javascript"]
229
+ #
230
+ # Returns an Array of [String path, Object value] matches.
231
+ def find_matching_path_for_extensions(path, basename, extensions)
232
+ matches = []
233
+ entries(path).each do |entry|
234
+ next unless File.basename(entry).start_with?(basename)
235
+ extname, value = match_path_extname(entry, extensions)
236
+ if basename == entry.chomp(extname)
237
+ filename = File.join(path, entry)
238
+ if file?(filename)
239
+ matches << [filename, value]
240
+ end
241
+ end
242
+ end
243
+ matches
244
+ end
245
+
166
246
  # Internal: Returns all parents for path
167
247
  #
168
248
  # path - String absolute filename or directory
@@ -272,7 +352,7 @@ module Sprockets
272
352
  Thread.current.object_id,
273
353
  Process.pid,
274
354
  rand(1000000)
275
- ].join('.')
355
+ ].join('.'.freeze)
276
356
  tmpname = File.join(dirname, basename)
277
357
 
278
358
  File.open(tmpname, 'wb+') do |f|
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'sprockets/path_utils'
2
3
  require 'sprockets/utils'
3
4
 
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+ module Sprockets
3
+ module Preprocessors
4
+ # Private: Adds a default map to assets when one is not present
5
+ #
6
+ # If the input file already has a source map, it effectively returns the original
7
+ # result. Otherwise it maps 1 for 1 lines original to generated. This is needed
8
+ # Because other generators run after might depend on having a valid source map
9
+ # available.
10
+ class DefaultSourceMap
11
+ def call(input)
12
+ result = { data: input[:data] }
13
+ map = input[:metadata][:map]
14
+ filename = input[:filename]
15
+ load_path = input[:load_path]
16
+ lines = input[:data].lines.length
17
+ basename = File.basename(filename)
18
+ mime_exts = input[:environment].config[:mime_exts]
19
+ pipeline_exts = input[:environment].config[:pipeline_exts]
20
+ if map.nil? || map.empty?
21
+ result[:map] = {
22
+ "version" => 3,
23
+ "file" => PathUtils.split_subpath(load_path, filename),
24
+ "mappings" => default_mappings(lines),
25
+ "sources" => [PathUtils.set_pipeline(basename, mime_exts, pipeline_exts, :source)],
26
+ "names" => []
27
+ }
28
+ else
29
+ result[:map] = map
30
+ end
31
+
32
+ result[:map]["x_sprockets_linecount"] = lines
33
+ return result
34
+ end
35
+
36
+ private
37
+
38
+ def default_mappings(lines)
39
+ if (lines == 0)
40
+ ""
41
+ elsif (lines == 1)
42
+ "AAAA"
43
+ else
44
+ "AAAA;" + "AACA;"*(lines - 2) + "AACA"
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,7 +1,5 @@
1
- require 'sprockets/engines'
1
+ # frozen_string_literal: true
2
2
  require 'sprockets/file_reader'
3
- require 'sprockets/legacy_proc_processor'
4
- require 'sprockets/legacy_tilt_processor'
5
3
  require 'sprockets/mime'
6
4
  require 'sprockets/processor_utils'
7
5
  require 'sprockets/uri_utils'
@@ -17,9 +15,14 @@ module Sprockets
17
15
  config[:pipelines]
18
16
  end
19
17
 
18
+ # Registers a pipeline that will be called by `call_processor` method.
20
19
  def register_pipeline(name, proc = nil, &block)
21
20
  proc ||= block
22
21
 
22
+ self.config = hash_reassoc(config, :pipeline_exts) do |pipeline_exts|
23
+ pipeline_exts.merge(".#{name}".freeze => name.to_sym)
24
+ end
25
+
23
26
  self.config = hash_reassoc(config, :pipelines) do |pipelines|
24
27
  pipelines.merge(name.to_sym => proc)
25
28
  end
@@ -43,12 +46,13 @@ module Sprockets
43
46
  #
44
47
  # A block can be passed for to create a shorthand processor.
45
48
  #
46
- # register_preprocessor 'text/css', :my_processor do |context, data|
47
- # data.gsub(...)
49
+ # register_preprocessor 'text/css' do |input|
50
+ # input[:data].gsub(...)
48
51
  # end
49
52
  #
50
53
  def register_preprocessor(*args, &block)
51
54
  register_config_processor(:preprocessors, *args, &block)
55
+ compute_transformers!(self.config[:registered_transformers])
52
56
  end
53
57
  alias_method :register_processor, :register_preprocessor
54
58
 
@@ -58,12 +62,13 @@ module Sprockets
58
62
  #
59
63
  # A block can be passed for to create a shorthand processor.
60
64
  #
61
- # register_postprocessor 'application/javascript', :my_processor do |context, data|
62
- # data.gsub(...)
65
+ # register_postprocessor 'application/javascript' do |input|
66
+ # input[:data].gsub(...)
63
67
  # end
64
68
  #
65
69
  def register_postprocessor(*args, &block)
66
70
  register_config_processor(:postprocessors, *args, &block)
71
+ compute_transformers!(self.config[:registered_transformers])
67
72
  end
68
73
 
69
74
  # Remove Preprocessor `klass` for `mime_type`.
@@ -72,6 +77,7 @@ module Sprockets
72
77
  #
73
78
  def unregister_preprocessor(*args)
74
79
  unregister_config_processor(:preprocessors, *args)
80
+ compute_transformers!(self.config[:registered_transformers])
75
81
  end
76
82
  alias_method :unregister_processor, :unregister_preprocessor
77
83
 
@@ -81,6 +87,7 @@ module Sprockets
81
87
  #
82
88
  def unregister_postprocessor(*args)
83
89
  unregister_config_processor(:postprocessors, *args)
90
+ compute_transformers!(self.config[:registered_transformers])
84
91
  end
85
92
 
86
93
  # Bundle Processors are ran on concatenated assets rather than
@@ -95,8 +102,8 @@ module Sprockets
95
102
  #
96
103
  # A block can be passed for to create a shorthand processor.
97
104
  #
98
- # register_bundle_processor 'application/javascript', :my_processor do |context, data|
99
- # data.gsub(...)
105
+ # register_bundle_processor 'application/javascript' do |input|
106
+ # input[:data].gsub(...)
100
107
  # end
101
108
  #
102
109
  def register_bundle_processor(*args, &block)
@@ -123,7 +130,7 @@ module Sprockets
123
130
  #
124
131
  # mime_type - String MIME Type. Use '*/*' applies to all types.
125
132
  # key - Symbol metadata key
126
- # initial - Initial memo to pass to the reduce funciton (default: nil)
133
+ # initial - Initial memo to pass to the reduce function (default: nil)
127
134
  # block - Proc accepting the memo accumulator and current value
128
135
  #
129
136
  # Returns nothing.
@@ -154,46 +161,44 @@ module Sprockets
154
161
  protected
155
162
  def resolve_processors_cache_key_uri(uri)
156
163
  params = parse_uri_query_params(uri[11..-1])
157
- params[:engine_extnames] = params[:engines] ? params[:engines].split(',') : []
158
- processors = processors_for(params[:type], params[:file_type], params[:engine_extnames], params[:pipeline])
164
+ processors = processors_for(params[:type], params[:file_type], params[:pipeline])
159
165
  processors_cache_keys(processors)
160
166
  end
161
167
 
162
- def build_processors_uri(type, file_type, engine_extnames, pipeline)
163
- engines = engine_extnames.join(',') if engine_extnames.any?
168
+ def build_processors_uri(type, file_type, pipeline)
164
169
  query = encode_uri_query_params(
165
170
  type: type,
166
171
  file_type: file_type,
167
- engines: engines,
168
172
  pipeline: pipeline
169
173
  )
170
174
  "processors:#{query}"
171
175
  end
172
176
 
173
- def processors_for(type, file_type, engine_extnames, pipeline)
177
+ def processors_for(type, file_type, pipeline)
174
178
  pipeline ||= :default
175
- config[:pipelines][pipeline.to_sym].call(self, type, file_type, engine_extnames)
179
+ if fn = config[:pipelines][pipeline.to_sym]
180
+ fn.call(self, type, file_type)
181
+ else
182
+ raise Error, "no pipeline: #{pipeline}"
183
+ end
176
184
  end
177
185
 
178
- def default_processors_for(type, file_type, engine_extnames)
186
+ def default_processors_for(type, file_type)
179
187
  bundled_processors = config[:bundle_processors][type]
180
188
  if bundled_processors.any?
181
189
  bundled_processors
182
190
  else
183
- self_processors_for(type, file_type, engine_extnames)
191
+ self_processors_for(type, file_type)
184
192
  end
185
193
  end
186
194
 
187
- def self_processors_for(type, file_type, engine_extnames)
195
+ def self_processors_for(type, file_type)
188
196
  processors = []
189
197
 
190
198
  processors.concat config[:postprocessors][type]
191
-
192
199
  if type != file_type && processor = config[:transformers][file_type][type]
193
200
  processors << processor
194
201
  end
195
-
196
- processors.concat engine_extnames.map { |ext| engines[ext] }
197
202
  processors.concat config[:preprocessors][file_type]
198
203
 
199
204
  if processors.any? || mime_type_charset_detecter(type)
@@ -204,55 +209,20 @@ module Sprockets
204
209
  end
205
210
 
206
211
  private
207
- def register_config_processor(type, mime_type, klass, proc = nil, &block)
208
- proc ||= block
209
- processor = wrap_processor(klass, proc)
212
+ def register_config_processor(type, mime_type, processor = nil, &block)
213
+ processor ||= block
210
214
 
211
215
  self.config = hash_reassoc(config, type, mime_type) do |processors|
212
216
  processors.unshift(processor)
213
217
  processors
214
218
  end
215
-
216
- compute_transformers!
217
219
  end
218
220
 
219
- def unregister_config_processor(type, mime_type, klass)
220
- if klass.is_a?(String) || klass.is_a?(Symbol)
221
- klass = config[type][mime_type].detect do |cls|
222
- cls.respond_to?(:name) && cls.name == "Sprockets::LegacyProcProcessor (#{klass})"
223
- end
224
- end
225
-
221
+ def unregister_config_processor(type, mime_type, processor)
226
222
  self.config = hash_reassoc(config, type, mime_type) do |processors|
227
- processors.delete(klass)
223
+ processors.delete_if { |p| p == processor || p.class == processor }
228
224
  processors
229
225
  end
230
-
231
- compute_transformers!
232
- end
233
-
234
- def deprecate_legacy_processor_interface(interface)
235
- msg = "You are using a deprecated processor interface #{ interface.inspect }.\n" +
236
- "Please update your processor interface:\n" +
237
- "https://github.com/rails/sprockets/blob/master/guides/extending_sprockets.md#supporting-all-versions-of-sprockets-in-processors\n"
238
-
239
- Deprecation.new([caller[3]]).warn msg
240
- end
241
-
242
- def wrap_processor(klass, proc)
243
- if !proc
244
- if klass.respond_to?(:call)
245
- klass
246
- else
247
- deprecate_legacy_processor_interface(klass)
248
- LegacyTiltProcessor.new(klass)
249
- end
250
- elsif proc.respond_to?(:arity) && proc.arity == 2
251
- deprecate_legacy_processor_interface(proc)
252
- LegacyProcProcessor.new(klass.to_s, proc)
253
- else
254
- proc
255
- end
256
226
  end
257
227
  end
258
228
  end
@@ -1,11 +1,12 @@
1
+ # frozen_string_literal: true
1
2
  require 'set'
2
3
 
3
4
  module Sprockets
4
5
  # Functional utilities for dealing with Processor functions.
5
6
  #
6
- # A Processor is a general function that my modify or transform an asset as
7
+ # A Processor is a general function that may modify or transform an asset as
7
8
  # part of the pipeline. CoffeeScript to JavaScript conversion, Minification
8
- # or Concatenation are all implemented as seperate Processor steps.
9
+ # or Concatenation are all implemented as separate Processor steps.
9
10
  #
10
11
  # Processors maybe any object that responds to call. So procs or a class that
11
12
  # defines a self.call method.
@@ -16,26 +17,34 @@ module Sprockets
16
17
  module ProcessorUtils
17
18
  extend self
18
19
 
20
+ class CompositeProcessor < Struct.new(:processor_strategy, :param, :processors) # :nodoc:
21
+ SINGULAR = lambda { |param, input| ProcessorUtils.call_processor param, input }
22
+ PLURAL = lambda { |param, input| ProcessorUtils.call_processors param, input }
23
+
24
+ def self.create(processors)
25
+ if processors.length == 1
26
+ new SINGULAR, processors.first, processors
27
+ else
28
+ new PLURAL, processors, processors
29
+ end
30
+ end
31
+
32
+ def call(input)
33
+ processor_strategy.call param, input
34
+ end
35
+
36
+ def cache_key
37
+ ProcessorUtils.processors_cache_keys(processors)
38
+ end
39
+ end
40
+
19
41
  # Public: Compose processors in right to left order.
20
42
  #
21
43
  # processors - Array of processors callables
22
44
  #
23
45
  # Returns a composed Proc.
24
46
  def compose_processors(*processors)
25
- context = self
26
-
27
- if processors.length == 1
28
- obj = method(:call_processor).to_proc.curry[processors.first]
29
- else
30
- obj = method(:call_processors).to_proc.curry[processors]
31
- end
32
-
33
- metaclass = (class << obj; self; end)
34
- metaclass.send(:define_method, :cache_key) do
35
- context.processors_cache_keys(processors)
36
- end
37
-
38
- obj
47
+ CompositeProcessor.create processors
39
48
  end
40
49
 
41
50
  # Public: Invoke list of processors in right to left order.
@@ -109,8 +118,9 @@ module Sprockets
109
118
  Symbol,
110
119
  TrueClass,
111
120
  FalseClass,
112
- NilClass
113
- ] + (0.class == Integer ? [Integer] : [Bignum, Fixnum])).freeze
121
+ NilClass,
122
+ Integer
123
+ ]).freeze
114
124
 
115
125
  # Internal: Set of all nested compound metadata types that can nest values.
116
126
  VALID_METADATA_COMPOUND_TYPES = Set.new([
@@ -152,29 +162,9 @@ module Sprockets
152
162
  if !key.instance_of?(Symbol)
153
163
  raise TypeError, "processor metadata[#{key.inspect}] expected to be a Symbol"
154
164
  end
155
-
156
- if !valid_processor_metadata_value?(value)
157
- raise TypeError, "processor metadata[:#{key}] returned a complex type: #{value.inspect}\n" +
158
- "Only #{VALID_METADATA_TYPES.to_a.join(", ")} maybe used."
159
- end
160
165
  end
161
166
 
162
167
  result
163
168
  end
164
-
165
- # Internal: Validate object is in validate metadata whitelist.
166
- #
167
- # value - Any Object
168
- #
169
- # Returns true if class is in whitelist otherwise false.
170
- def valid_processor_metadata_value?(value)
171
- if VALID_METADATA_VALUE_TYPES_HASH[value.class]
172
- true
173
- elsif VALID_METADATA_COMPOUND_TYPES_HASH[value.class]
174
- value.all? { |v| valid_processor_metadata_value?(v) }
175
- else
176
- false
177
- end
178
- end
179
169
  end
180
170
  end