sprockets 3.0.0.beta.6 → 3.0.0.beta.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +171 -100
  3. data/lib/rake/sprocketstask.rb +2 -2
  4. data/lib/sprockets.rb +69 -63
  5. data/lib/sprockets/asset.rb +2 -61
  6. data/lib/sprockets/autoload_processor.rb +48 -0
  7. data/lib/sprockets/base.rb +4 -6
  8. data/lib/sprockets/bower.rb +8 -5
  9. data/lib/sprockets/bundle.rb +9 -13
  10. data/lib/sprockets/cache.rb +19 -14
  11. data/lib/sprockets/cache/file_store.rb +2 -1
  12. data/lib/sprockets/cached_environment.rb +15 -68
  13. data/lib/sprockets/closure_compressor.rb +17 -4
  14. data/lib/sprockets/coffee_script_processor.rb +26 -0
  15. data/lib/sprockets/coffee_script_template.rb +3 -20
  16. data/lib/sprockets/compressing.rb +10 -4
  17. data/lib/sprockets/configuration.rb +21 -37
  18. data/lib/sprockets/context.rb +37 -67
  19. data/lib/sprockets/dependencies.rb +73 -0
  20. data/lib/sprockets/digest_utils.rb +8 -2
  21. data/lib/sprockets/directive_processor.rb +122 -165
  22. data/lib/sprockets/eco_processor.rb +32 -0
  23. data/lib/sprockets/eco_template.rb +3 -26
  24. data/lib/sprockets/ejs_processor.rb +31 -0
  25. data/lib/sprockets/ejs_template.rb +3 -25
  26. data/lib/sprockets/encoding_utils.rb +9 -21
  27. data/lib/sprockets/engines.rb +25 -27
  28. data/lib/sprockets/environment.rb +9 -1
  29. data/lib/sprockets/erb_processor.rb +30 -0
  30. data/lib/sprockets/erb_template.rb +3 -20
  31. data/lib/sprockets/file_reader.rb +15 -0
  32. data/lib/sprockets/http_utils.rb +2 -0
  33. data/lib/sprockets/jst_processor.rb +9 -2
  34. data/lib/sprockets/legacy.rb +212 -3
  35. data/lib/sprockets/legacy_tilt_processor.rb +1 -1
  36. data/lib/sprockets/loader.rb +95 -89
  37. data/lib/sprockets/manifest.rb +23 -59
  38. data/lib/sprockets/mime.rb +28 -41
  39. data/lib/sprockets/path_dependency_utils.rb +76 -0
  40. data/lib/sprockets/path_utils.rb +21 -1
  41. data/lib/sprockets/paths.rb +23 -8
  42. data/lib/sprockets/processing.rb +102 -91
  43. data/lib/sprockets/processor_utils.rb +97 -0
  44. data/lib/sprockets/resolve.rb +110 -97
  45. data/lib/sprockets/sass_cache_store.rb +2 -2
  46. data/lib/sprockets/sass_compressor.rb +17 -4
  47. data/lib/sprockets/sass_functions.rb +2 -2
  48. data/lib/sprockets/sass_importer.rb +2 -2
  49. data/lib/sprockets/sass_processor.rb +305 -0
  50. data/lib/sprockets/sass_template.rb +4 -286
  51. data/lib/sprockets/server.rb +1 -13
  52. data/lib/sprockets/transformers.rb +62 -25
  53. data/lib/sprockets/uglifier_compressor.rb +17 -4
  54. data/lib/sprockets/uri_utils.rb +190 -0
  55. data/lib/sprockets/utils.rb +87 -6
  56. data/lib/sprockets/version.rb +1 -1
  57. data/lib/sprockets/yui_compressor.rb +17 -4
  58. metadata +14 -5
  59. data/lib/sprockets/asset_uri.rb +0 -80
  60. data/lib/sprockets/lazy_processor.rb +0 -15
@@ -106,50 +106,6 @@ module Sprockets
106
106
  @data['files'] ||= {}
107
107
  end
108
108
 
109
- # Deprecated: Compile logical path matching filter into a proc that can be
110
- # passed to logical_paths.select(&proc).
111
- #
112
- # compile_match_filter(proc { |logical_path|
113
- # File.extname(logical_path) == '.js'
114
- # })
115
- #
116
- # compile_match_filter(/application.js/)
117
- #
118
- # compile_match_filter("foo/*.js")
119
- #
120
- # Returns a Proc or raise a TypeError.
121
- def self.compile_match_filter(filter)
122
- # If the filter is already a proc, great nothing to do.
123
- if filter.respond_to?(:call)
124
- filter
125
- # If the filter is a regexp, wrap it in a proc that tests it against the
126
- # logical path.
127
- elsif filter.is_a?(Regexp)
128
- proc { |logical_path| filter.match(logical_path) }
129
- elsif filter.is_a?(String)
130
- # If its an absolute path, detect the matching full filename
131
- if PathUtils.absolute_path?(filter)
132
- proc { |logical_path, filename| filename == filter.to_s }
133
- else
134
- # Otherwise do an fnmatch against the logical path.
135
- proc { |logical_path| File.fnmatch(filter.to_s, logical_path) }
136
- end
137
- else
138
- raise TypeError, "unknown filter type: #{filter.inspect}"
139
- end
140
- end
141
-
142
- # Deprecated: Filter logical paths in environment. Useful for selecting what
143
- # files you want to compile.
144
- #
145
- # Returns an Enumerator.
146
- def filter_logical_paths(*args)
147
- filters = args.flatten.map { |arg| self.class.compile_match_filter(arg) }
148
- environment.logical_paths.select do |a, b|
149
- filters.any? { |f| f.call(a, b) }
150
- end
151
- end
152
-
153
109
  # Public: Find all assets matching pattern set in environment.
154
110
  #
155
111
  # Returns Enumerator of Assets.
@@ -162,6 +118,7 @@ module Sprockets
162
118
 
163
119
  filters = args.flatten.map { |arg| self.class.compile_match_filter(arg) }
164
120
 
121
+ environment = self.environment.cached
165
122
  environment.logical_paths do |logical_path, filename|
166
123
  if filters.any? { |f| f.call(logical_path, filename) }
167
124
  environment.find_all_linked_assets(filename) do |asset|
@@ -173,9 +130,6 @@ module Sprockets
173
130
  nil
174
131
  end
175
132
 
176
- # Deprecated alias.
177
- alias_method :find_logical_paths, :filter_logical_paths
178
-
179
133
  # Compile and write asset to directory. The asset is written to a
180
134
  # fingerprinted filename like
181
135
  # `application-2e8e9a7c6b0aafa0c9bdeec90ea30213.js`. An entry is
@@ -240,25 +194,34 @@ module Sprockets
240
194
  end
241
195
 
242
196
  # Cleanup old assets in the compile directory. By default it will
243
- # keep the latest version plus 2 backups.
244
- def clean(keep = 2)
197
+ # keep the latest version, 2 backups and any created within the past hour.
198
+ #
199
+ # Examples
200
+ #
201
+ # To force only 1 backup to be kept, set count=1 and age=0.
202
+ #
203
+ # To only keep files created within the last 10 minutes, set count=0 and
204
+ # age=600.
205
+ #
206
+ def clean(count = 2, age = 3600)
245
207
  asset_versions = files.group_by { |_, attrs| attrs['logical_path'] }
246
208
 
247
209
  asset_versions.each do |logical_path, versions|
248
210
  current = assets[logical_path]
249
211
 
250
- backups = versions.reject { |path, _|
212
+ versions.reject { |path, _|
251
213
  path == current
252
214
  }.sort_by { |_, attrs|
253
215
  # Sort by timestamp
254
216
  Time.parse(attrs['mtime'])
255
- }.reverse
256
-
257
- # Keep the last N backups
258
- backups = backups[keep..-1] || []
259
-
260
- # Remove old assets
261
- backups.each { |path, _| remove(path) }
217
+ }.reverse.each_with_index.drop_while { |(_, attrs), index|
218
+ age = [0, Time.now - Time.parse(attrs['mtime'])].max
219
+ # Keep if under age or within the count limit
220
+ age < age || index < count
221
+ }.each { |(path, _), _|
222
+ # Remove old assets
223
+ remove(path)
224
+ }
262
225
  end
263
226
  end
264
227
 
@@ -272,9 +235,10 @@ module Sprockets
272
235
  protected
273
236
  # Persist manfiest back to FS
274
237
  def save
238
+ data = json_encode(@data)
275
239
  FileUtils.mkdir_p File.dirname(filename)
276
- File.open(filename, 'w') do |f|
277
- f.write json_encode(@data)
240
+ PathUtils.atomic_write(filename) do |f|
241
+ f.write(data)
278
242
  end
279
243
  end
280
244
 
@@ -1,9 +1,10 @@
1
1
  require 'sprockets/encoding_utils'
2
2
  require 'sprockets/http_utils'
3
+ require 'sprockets/utils'
3
4
 
4
5
  module Sprockets
5
6
  module Mime
6
- include HTTPUtils
7
+ include HTTPUtils, Utils
7
8
 
8
9
  # Public: Mapping of MIME type Strings to properties Hash.
9
10
  #
@@ -13,7 +14,9 @@ module Sprockets
13
14
  # charset - Default Encoding or function to detect encoding
14
15
  #
15
16
  # Returns Hash.
16
- attr_reader :mime_types
17
+ def mime_types
18
+ config[:mime_types]
19
+ end
17
20
 
18
21
  # Internal: Mapping of MIME extension Strings to MIME type Strings.
19
22
  #
@@ -27,7 +30,9 @@ module Sprockets
27
30
  # value - MIME Type String
28
31
  #
29
32
  # Returns Hash.
30
- attr_reader :mime_exts
33
+ def mime_exts
34
+ config[:mime_exts]
35
+ end
31
36
 
32
37
  # Public: Register a new mime type.
33
38
  #
@@ -49,20 +54,25 @@ module Sprockets
49
54
  }
50
55
 
51
56
  charset = options[:charset]
52
- charset ||= EncodingUtils::DETECT if mime_type.start_with?('text/')
57
+ charset ||= :default if mime_type.start_with?('text/')
58
+ charset = EncodingUtils::CHARSET_DETECT[charset] if charset.is_a?(Symbol)
53
59
 
54
- mutate_config(:mime_exts) do |mime_exts|
60
+ self.config = hash_reassoc(config, :mime_exts) do |mime_exts|
55
61
  extnames.each do |extname|
56
62
  mime_exts[extname] = mime_type
57
63
  end
58
64
  mime_exts
59
65
  end
60
66
 
61
- mutate_config(:mime_types) do |mime_types|
67
+ self.config = hash_reassoc(config, :mime_types) do |mime_types|
62
68
  type = { extensions: extnames }
63
69
  type[:charset] = charset if charset
64
70
  mime_types.merge(mime_type => type)
65
71
  end
72
+
73
+ self.config = hash_reassoc(config, :_extnames) do
74
+ compute_extname_map
75
+ end
66
76
  end
67
77
 
68
78
  # Internal: Get detecter function for MIME type.
@@ -95,44 +105,21 @@ module Sprockets
95
105
  end
96
106
  end
97
107
 
98
- # Public: Mapping of supported HTTP Content/Transfer encodings
99
- #
100
- # key - String name
101
- # value - Method/Proc to encode data
102
- #
103
- # Returns Hash.
104
- attr_reader :encodings
105
-
106
- # Public: Register a new encoding.
107
- #
108
- # Examples
109
- #
110
- # register_encoding :gzip, EncodingUtils::GZIP
111
- #
112
- # key - String name
113
- # encode - Method/Proc to encode data
114
- #
115
- # Returns nothing.
116
- def register_encoding(name, encode)
117
- mutate_config(:encodings) do |encodings|
118
- encodings.merge(name.to_s => encode)
119
- end
120
- end
121
-
122
108
  private
123
- # Internal: Get a postprocessor to perform the encoding.
124
- #
125
- # encoding - String encoding.
126
- #
127
- # Returns an Array of Processors.
128
- def unwrap_encoding_processors(encoding)
129
- processors = []
130
- if encoder = self.encodings[encoding]
131
- processors << lambda do |input|
132
- { data: encoder.call(input[:data]), encoding: encoding }
109
+ def compute_extname_map
110
+ graph = {}
111
+
112
+ ([[nil, nil]] + mime_exts.to_a).each do |format_extname, format_type|
113
+ 3.times do |n|
114
+ engines.keys.permutation(n).each do |engine_extnames|
115
+ key = "#{format_extname}#{engine_extnames.join}"
116
+ type = format_type || engine_mime_types[engine_extnames.first]
117
+ graph[key] = {type: type, engines: engine_extnames}
118
+ end
133
119
  end
134
120
  end
135
- processors
121
+
122
+ graph
136
123
  end
137
124
  end
138
125
  end
@@ -0,0 +1,76 @@
1
+ require 'set'
2
+ require 'sprockets/path_utils'
3
+ require 'sprockets/uri_utils'
4
+
5
+ module Sprockets
6
+ # Internal: Related PathUtils helpers that also track all the file system
7
+ # calls they make for caching purposes. All functions return a standard
8
+ # return value and a Set of cache dependency URIs that can be used in the
9
+ # future to see if the returned value should be invalidated from cache.
10
+ #
11
+ # entries_with_dependencies("app/assets/javascripts")
12
+ # # => [
13
+ # # ["application.js", "projects.js", "users.js", ...]
14
+ # # #<Set: {"file-digest:/path/to/app/assets/javascripts"}>
15
+ # # ]
16
+ #
17
+ # The returned dependency set can be passed to resolve_dependencies(deps)
18
+ # to check if the returned result is still fresh. In this case, entry always
19
+ # returns a single path, but multiple calls should accumulate dependencies
20
+ # into a single set thats saved off and checked later.
21
+ #
22
+ # resolve_dependencies(deps)
23
+ # # => "\x01\x02\x03"
24
+ #
25
+ # Later, resolving the same set again will produce a different hash if
26
+ # something on the file system has changed.
27
+ #
28
+ # resolve_dependencies(deps)
29
+ # # => "\x03\x04\x05"
30
+ #
31
+ module PathDependencyUtils
32
+ include PathUtils
33
+ include URIUtils
34
+
35
+ # Internal: List directory entries and return a set of dependencies that
36
+ # would invalid the cached return result.
37
+ #
38
+ # See PathUtils#entries
39
+ #
40
+ # path - String directory path
41
+ #
42
+ # Returns an Array of entry names and a Set of dependency URIs.
43
+ def entries_with_dependencies(path)
44
+ return entries(path), Set.new([build_file_digest_uri(path)])
45
+ end
46
+
47
+ # Internal: List directory filenames and associated Stats under a
48
+ # directory.
49
+ #
50
+ # See PathUtils#stat_directory
51
+ #
52
+ # dir - A String directory
53
+ #
54
+ # Returns an Array of filenames and a Set of dependency URIs.
55
+ def stat_directory_with_dependencies(dir)
56
+ return stat_directory(dir).to_a, Set.new([build_file_digest_uri(dir)])
57
+ end
58
+
59
+ # Internal: List directory filenames and associated Stats under an entire
60
+ # directory tree.
61
+ #
62
+ # See PathUtils#stat_sorted_tree
63
+ #
64
+ # dir - A String directory
65
+ #
66
+ # Returns an Array of filenames and a Set of dependency URIs.
67
+ def stat_sorted_tree_with_dependencies(dir)
68
+ deps = Set.new([build_file_digest_uri(dir)])
69
+ results = stat_sorted_tree(dir).map do |path, stat|
70
+ deps << build_file_digest_uri(path) if stat.directory?
71
+ [path, stat]
72
+ end
73
+ return results, deps
74
+ end
75
+ end
76
+ end
@@ -57,7 +57,7 @@ module Sprockets
57
57
  require 'pathname'
58
58
 
59
59
  # On Windows, ALT_SEPARATOR is \
60
- # Delegate to Pathname nice the logic gets complex.
60
+ # Delegate to Pathname since the logic gets complex.
61
61
  def absolute_path?(path)
62
62
  Pathname.new(path).absolute?
63
63
  end
@@ -91,6 +91,7 @@ module Sprockets
91
91
  # Returns relative String path if subpath is a subpath of path, or nil if
92
92
  # subpath is outside of path.
93
93
  def split_subpath(path, subpath)
94
+ return "" if path == subpath
94
95
  path = File.join(path, '')
95
96
  if subpath.start_with?(path)
96
97
  subpath[path.length..-1]
@@ -123,6 +124,25 @@ module Sprockets
123
124
  File.basename(path).scan(/\.[^.]+/)
124
125
  end
125
126
 
127
+ # Internal: Match path extnames against available extensions.
128
+ #
129
+ # path - String
130
+ # extensions - Hash of String extnames to values
131
+ #
132
+ # Returns [String extname, Object value] or nil nothing matched.
133
+ def match_path_extname(path, extensions)
134
+ match, key = nil, ""
135
+ path_extnames(path).reverse_each do |extname|
136
+ key.prepend(extname)
137
+ if value = extensions[key]
138
+ match = [key.dup, value]
139
+ elsif match
140
+ break
141
+ end
142
+ end
143
+ match
144
+ end
145
+
126
146
  # Internal: Returns all parents for path
127
147
  #
128
148
  # path - String absolute filename or directory
@@ -1,26 +1,41 @@
1
1
  require 'sprockets/path_utils'
2
+ require 'sprockets/utils'
2
3
 
3
4
  module Sprockets
4
5
  module Paths
5
- include PathUtils
6
+ include PathUtils, Utils
6
7
 
7
8
  # Returns `Environment` root.
8
9
  #
9
10
  # All relative paths are expanded with root as its base. To be
10
11
  # useful set this to your applications root directory. (`Rails.root`)
11
- attr_reader :root
12
+ def root
13
+ config[:root]
14
+ end
15
+
16
+ # Internal: Change Environment root.
17
+ #
18
+ # Only the initializer should change the root.
19
+ def root=(path)
20
+ self.config = hash_reassoc(config, :root) do
21
+ File.expand_path(path)
22
+ end
23
+ end
24
+ private :root=
12
25
 
13
26
  # Returns an `Array` of path `String`s.
14
27
  #
15
28
  # These paths will be used for asset logical path lookups.
16
- attr_reader :paths
29
+ def paths
30
+ config[:paths]
31
+ end
17
32
 
18
33
  # Prepend a `path` to the `paths` list.
19
34
  #
20
35
  # Paths at the end of the `Array` have the least priority.
21
36
  def prepend_path(path)
22
- mutate_config(:paths) do |paths|
23
- path = File.expand_path(path, root).dup.freeze
37
+ self.config = hash_reassoc(config, :paths) do |paths|
38
+ path = File.expand_path(path, root).freeze
24
39
  paths.unshift(path)
25
40
  end
26
41
  end
@@ -29,8 +44,8 @@ module Sprockets
29
44
  #
30
45
  # Paths at the beginning of the `Array` have a higher priority.
31
46
  def append_path(path)
32
- mutate_config(:paths) do |paths|
33
- path = File.expand_path(path, root).dup.freeze
47
+ self.config = hash_reassoc(config, :paths) do |paths|
48
+ path = File.expand_path(path, root).freeze
34
49
  paths.push(path)
35
50
  end
36
51
  end
@@ -41,7 +56,7 @@ module Sprockets
41
56
  # completely wipe the paths list and reappend them in the order
42
57
  # you want.
43
58
  def clear_paths
44
- mutate_config(:paths) do |paths|
59
+ self.config = hash_reassoc(config, :paths) do |paths|
45
60
  paths.clear
46
61
  end
47
62
  end
@@ -1,41 +1,27 @@
1
1
  require 'sprockets/engines'
2
- require 'sprockets/lazy_processor'
3
2
  require 'sprockets/legacy_proc_processor'
4
3
  require 'sprockets/legacy_tilt_processor'
5
4
  require 'sprockets/mime'
5
+ require 'sprockets/processor_utils'
6
+ require 'sprockets/uri_utils'
6
7
  require 'sprockets/utils'
7
8
 
8
9
  module Sprockets
9
10
  # `Processing` is an internal mixin whose public methods are exposed on
10
11
  # the `Environment` and `CachedEnvironment` classes.
11
12
  module Processing
13
+ include ProcessorUtils, URIUtils, Utils
14
+
12
15
  # Preprocessors are ran before Postprocessors and Engine
13
16
  # processors.
14
- attr_reader :preprocessors
15
-
16
- # Internal: Find and load preprocessors by mime type.
17
- #
18
- # mime_type - String MIME type.
19
- #
20
- # Returns Array of Procs.
21
- def unwrap_preprocessors(mime_type)
22
- preprocessors[mime_type].map do |processor|
23
- unwrap_processor(processor)
24
- end
17
+ def preprocessors
18
+ config[:preprocessors]
25
19
  end
20
+ alias_method :processors, :preprocessors
26
21
 
27
22
  # Postprocessors are ran after Preprocessors and Engine processors.
28
- attr_reader :postprocessors
29
-
30
- # Internal: Find and load postprocessors by mime type.
31
- #
32
- # mime_type - String MIME type.
33
- #
34
- # Returns Array of Procs.
35
- def unwrap_postprocessors(mime_type)
36
- postprocessors[mime_type].map do |processor|
37
- unwrap_processor(processor)
38
- end
23
+ def postprocessors
24
+ config[:postprocessors]
39
25
  end
40
26
 
41
27
  # Registers a new Preprocessor `klass` for `mime_type`.
@@ -48,12 +34,10 @@ module Sprockets
48
34
  # data.gsub(...)
49
35
  # end
50
36
  #
51
- def register_preprocessor(mime_type, klass, &block)
52
- mutate_hash_config(:preprocessors, mime_type) do |processors|
53
- processors.push(wrap_processor(klass, block))
54
- processors
55
- end
37
+ def register_preprocessor(*args, &block)
38
+ register_config_processor(:preprocessors, *args, &block)
56
39
  end
40
+ alias_method :register_processor, :register_preprocessor
57
41
 
58
42
  # Registers a new Postprocessor `klass` for `mime_type`.
59
43
  #
@@ -65,61 +49,31 @@ module Sprockets
65
49
  # data.gsub(...)
66
50
  # end
67
51
  #
68
- def register_postprocessor(mime_type, klass, proc = nil, &block)
69
- proc ||= block
70
- mutate_hash_config(:postprocessors, mime_type) do |processors|
71
- processors.push(wrap_processor(klass, proc))
72
- processors
73
- end
52
+ def register_postprocessor(*args, &block)
53
+ register_config_processor(:postprocessors, *args, &block)
74
54
  end
75
55
 
76
56
  # Remove Preprocessor `klass` for `mime_type`.
77
57
  #
78
58
  # unregister_preprocessor 'text/css', Sprockets::DirectiveProcessor
79
59
  #
80
- def unregister_preprocessor(mime_type, klass)
81
- if klass.is_a?(String) || klass.is_a?(Symbol)
82
- klass = preprocessors[mime_type].detect { |cls|
83
- cls.respond_to?(:name) && cls.name == "Sprockets::LegacyProcProcessor (#{klass})"
84
- }
85
- end
86
-
87
- mutate_hash_config(:preprocessors, mime_type) do |processors|
88
- processors.delete(klass)
89
- processors
90
- end
60
+ def unregister_preprocessor(*args)
61
+ unregister_config_processor(:preprocessors, *args)
91
62
  end
63
+ alias_method :unregister_processor, :unregister_preprocessor
92
64
 
93
65
  # Remove Postprocessor `klass` for `mime_type`.
94
66
  #
95
67
  # unregister_postprocessor 'text/css', Sprockets::DirectiveProcessor
96
68
  #
97
- def unregister_postprocessor(mime_type, klass)
98
- if klass.is_a?(String) || klass.is_a?(Symbol)
99
- klass = postprocessors[mime_type].detect { |cls|
100
- cls.respond_to?(:name) && cls.name == "Sprockets::LegacyProcProcessor (#{klass})"
101
- }
102
- end
103
-
104
- mutate_hash_config(:postprocessors, mime_type) do |processors|
105
- processors.delete(klass)
106
- processors
107
- end
69
+ def unregister_postprocessor(*args)
70
+ unregister_config_processor(:postprocessors, *args)
108
71
  end
109
72
 
110
73
  # Bundle Processors are ran on concatenated assets rather than
111
74
  # individual files.
112
- attr_reader :bundle_processors
113
-
114
- # Internal: Find and load bundle processors by mime type.
115
- #
116
- # mime_type - String MIME type.
117
- #
118
- # Returns Array of Procs.
119
- def unwrap_bundle_processors(mime_type)
120
- bundle_processors[mime_type].map do |processor|
121
- unwrap_processor(processor)
122
- end
75
+ def bundle_processors
76
+ config[:bundle_processors]
123
77
  end
124
78
 
125
79
  # Registers a new Bundle Processor `klass` for `mime_type`.
@@ -132,33 +86,23 @@ module Sprockets
132
86
  # data.gsub(...)
133
87
  # end
134
88
  #
135
- def register_bundle_processor(mime_type, klass, &block)
136
- mutate_hash_config(:bundle_processors, mime_type) do |processors|
137
- processors.push(wrap_processor(klass, block))
138
- processors
139
- end
89
+ def register_bundle_processor(*args, &block)
90
+ register_config_processor(:bundle_processors, *args, &block)
140
91
  end
141
92
 
142
93
  # Remove Bundle Processor `klass` for `mime_type`.
143
94
  #
144
95
  # unregister_bundle_processor 'application/javascript', Sprockets::DirectiveProcessor
145
96
  #
146
- def unregister_bundle_processor(mime_type, klass)
147
- if klass.is_a?(String) || klass.is_a?(Symbol)
148
- klass = bundle_processors[mime_type].detect { |cls|
149
- cls.respond_to?(:name) && cls.name == "Sprockets::LegacyProcProcessor (#{klass})"
150
- }
151
- end
152
-
153
- mutate_hash_config(:bundle_processors, mime_type) do |processors|
154
- processors.delete(klass)
155
- processors
156
- end
97
+ def unregister_bundle_processor(*args)
98
+ unregister_config_processor(:bundle_processors, *args)
157
99
  end
158
100
 
159
101
  # Internal: Two dimensional Hash of reducer functions for a given mime type
160
102
  # and asset metadata key.
161
- attr_reader :bundle_reducers
103
+ def bundle_reducers
104
+ config[:bundle_reducers]
105
+ end
162
106
 
163
107
  # Public: Register bundle metadata reducer function.
164
108
  #
@@ -195,7 +139,7 @@ module Sprockets
195
139
  raise ArgumentError, "wrong number of arguments (#{args.size} for 0..2)"
196
140
  end
197
141
 
198
- mutate_hash_config(:bundle_reducers, mime_type) do |reducers|
142
+ self.config = hash_reassoc(config, :bundle_reducers, mime_type) do |reducers|
199
143
  reducers.merge(key => [initial, reducer])
200
144
  end
201
145
  end
@@ -205,7 +149,7 @@ module Sprockets
205
149
  # mime_type - String MIME type
206
150
  #
207
151
  # Returns an Array of [initial, reducer_proc] pairs.
208
- def unwrap_bundle_reducers(mime_type)
152
+ def load_bundle_reducers(mime_type)
209
153
  self.bundle_reducers['*/*'].merge(self.bundle_reducers[mime_type])
210
154
  end
211
155
 
@@ -231,10 +175,81 @@ module Sprockets
231
175
  end
232
176
  end
233
177
 
178
+ protected
179
+ def resolve_processors_cache_key_uri(uri)
180
+ params = parse_uri_query_params(uri[11..-1])
181
+ params[:engine_extnames] = params[:engines] ? params[:engines].split(',') : []
182
+ processors = processors_for(params[:type], params[:file_type], params[:engine_extnames], params[:skip_bundle])
183
+ processors_cache_keys(processors)
184
+ end
185
+
186
+ def build_processors_uri(type, file_type, engine_extnames, skip_bundle)
187
+ engines = engine_extnames.join(',') if engine_extnames.any?
188
+ query = encode_uri_query_params(
189
+ type: type,
190
+ file_type: file_type,
191
+ engines: engines,
192
+ skip_bundle: skip_bundle
193
+ )
194
+ "processors:#{query}"
195
+ end
196
+
197
+ def processors_for(type, file_type, engine_extnames, skip_bundle)
198
+ processors = []
199
+
200
+ bundled_processors = skip_bundle ? [] : config[:bundle_processors][type]
201
+
202
+ if bundled_processors.any?
203
+ processors.concat bundled_processors
204
+ else
205
+ processors.concat config[:postprocessors][type]
206
+
207
+ if type != file_type && processor = transformers[file_type][type]
208
+ processors << processor
209
+ end
210
+
211
+ processors.concat engine_extnames.map { |ext| engines[ext] }
212
+ processors.concat config[:preprocessors][file_type]
213
+ end
214
+
215
+ if processors.any? || mime_type_charset_detecter(type)
216
+ processors << FileReader
217
+ end
218
+
219
+ processors
220
+ end
221
+
234
222
  private
223
+ def register_config_processor(type, mime_type, klass, proc = nil, &block)
224
+ proc ||= block
225
+ processor = wrap_processor(klass, proc)
226
+
227
+ self.config = hash_reassoc(config, type, mime_type) do |processors|
228
+ processors.unshift(processor)
229
+ processors
230
+ end
231
+
232
+ compute_transformers!
233
+ end
234
+
235
+ def unregister_config_processor(type, mime_type, klass)
236
+ if klass.is_a?(String) || klass.is_a?(Symbol)
237
+ klass = config[type][mime_type].detect do |cls|
238
+ cls.respond_to?(:name) && cls.name == "Sprockets::LegacyProcProcessor (#{klass})"
239
+ end
240
+ end
241
+
242
+ self.config = hash_reassoc(config, type, mime_type) do |processors|
243
+ processors.delete(klass)
244
+ processors
245
+ end
246
+
247
+ compute_transformers!
248
+ end
249
+
235
250
  def wrap_processor(klass, proc)
236
251
  if !proc
237
- if klass.class == Sprockets::LazyProcessor || klass.respond_to?(:call)
252
+ if klass.class == Sprockets::AutoloadProcessor || klass.respond_to?(:call)
238
253
  klass
239
254
  else
240
255
  LegacyTiltProcessor.new(klass)
@@ -245,9 +260,5 @@ module Sprockets
245
260
  proc
246
261
  end
247
262
  end
248
-
249
- def unwrap_processor(processor)
250
- processor.respond_to?(:unwrap) ? processor.unwrap : processor
251
- end
252
263
  end
253
264
  end