sprockets 1.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sprockets might be problematic. Click here for more details.

Files changed (64) hide show
  1. data/LICENSE +21 -0
  2. data/README.md +356 -0
  3. data/lib/sprockets.rb +26 -37
  4. data/lib/sprockets/asset.rb +212 -0
  5. data/lib/sprockets/asset_attributes.rb +158 -0
  6. data/lib/sprockets/base.rb +163 -0
  7. data/lib/sprockets/bundled_asset.rb +258 -0
  8. data/lib/sprockets/cache/file_store.rb +41 -0
  9. data/lib/sprockets/caching.rb +123 -0
  10. data/lib/sprockets/charset_normalizer.rb +41 -0
  11. data/lib/sprockets/context.rb +217 -0
  12. data/lib/sprockets/digest.rb +67 -0
  13. data/lib/sprockets/directive_processor.rb +380 -0
  14. data/lib/sprockets/eco_template.rb +38 -0
  15. data/lib/sprockets/ejs_template.rb +37 -0
  16. data/lib/sprockets/engines.rb +98 -0
  17. data/lib/sprockets/environment.rb +81 -40
  18. data/lib/sprockets/errors.rb +17 -0
  19. data/lib/sprockets/index.rb +79 -0
  20. data/lib/sprockets/jst_processor.rb +26 -0
  21. data/lib/sprockets/mime.rb +38 -0
  22. data/lib/sprockets/processing.rb +280 -0
  23. data/lib/sprockets/processor.rb +32 -0
  24. data/lib/sprockets/safety_colons.rb +28 -0
  25. data/lib/sprockets/server.rb +272 -0
  26. data/lib/sprockets/static_asset.rb +86 -0
  27. data/lib/sprockets/trail.rb +114 -0
  28. data/lib/sprockets/utils.rb +67 -0
  29. data/lib/sprockets/version.rb +1 -7
  30. metadata +212 -64
  31. data/Rakefile +0 -19
  32. data/bin/sprocketize +0 -54
  33. data/ext/nph-sprockets.cgi +0 -127
  34. data/lib/sprockets/concatenation.rb +0 -36
  35. data/lib/sprockets/error.rb +0 -5
  36. data/lib/sprockets/pathname.rb +0 -37
  37. data/lib/sprockets/preprocessor.rb +0 -91
  38. data/lib/sprockets/secretary.rb +0 -106
  39. data/lib/sprockets/source_file.rb +0 -54
  40. data/lib/sprockets/source_line.rb +0 -82
  41. data/test/fixtures/assets/images/script_with_assets/one.png +0 -1
  42. data/test/fixtures/assets/images/script_with_assets/two.png +0 -1
  43. data/test/fixtures/assets/stylesheets/script_with_assets.css +0 -1
  44. data/test/fixtures/constants.yml +0 -1
  45. data/test/fixtures/double_slash_comments_that_are_not_requires_should_be_ignored_when_strip_comments_is_false.js +0 -8
  46. data/test/fixtures/double_slash_comments_that_are_not_requires_should_be_removed_by_default.js +0 -2
  47. data/test/fixtures/multiline_comments_should_be_removed_by_default.js +0 -4
  48. data/test/fixtures/requiring_a_file_after_it_has_already_been_required_should_do_nothing.js +0 -5
  49. data/test/fixtures/requiring_a_file_that_does_not_exist_should_raise_an_error.js +0 -1
  50. data/test/fixtures/requiring_a_single_file_should_replace_the_require_comment_with_the_file_contents.js +0 -3
  51. data/test/fixtures/requiring_the_current_file_should_do_nothing.js +0 -1
  52. data/test/fixtures/src/constants.yml +0 -3
  53. data/test/fixtures/src/foo.js +0 -1
  54. data/test/fixtures/src/foo/bar.js +0 -4
  55. data/test/fixtures/src/foo/foo.js +0 -1
  56. data/test/fixtures/src/script_with_assets.js +0 -3
  57. data/test/test_concatenation.rb +0 -28
  58. data/test/test_environment.rb +0 -64
  59. data/test/test_helper.rb +0 -55
  60. data/test/test_pathname.rb +0 -43
  61. data/test/test_preprocessor.rb +0 -107
  62. data/test/test_secretary.rb +0 -83
  63. data/test/test_source_file.rb +0 -34
  64. data/test/test_source_line.rb +0 -89
@@ -0,0 +1,98 @@
1
+ require 'sprockets/eco_template'
2
+ require 'sprockets/ejs_template'
3
+ require 'sprockets/jst_processor'
4
+ require 'sprockets/utils'
5
+ require 'tilt'
6
+
7
+ module Sprockets
8
+ # `Engines` provides a global and `Environment` instance registry.
9
+ #
10
+ # An engine is a type of processor that is bound to an filename
11
+ # extension. `application.js.coffee` indicates that the
12
+ # `CoffeeScriptTemplate` engine will be ran on the file.
13
+ #
14
+ # Extensions can be stacked and will be evaulated from right to
15
+ # left. `application.js.coffee.erb` will first run `ERBTemplate`
16
+ # then `CoffeeScriptTemplate`.
17
+ #
18
+ # All `Engine`s must follow the `Tilt::Template` interface. It is
19
+ # recommended to subclass `Tilt::Template`.
20
+ #
21
+ # Its recommended that you register engine changes on your local
22
+ # `Environment` instance.
23
+ #
24
+ # environment.register_engine '.foo', FooProcessor
25
+ #
26
+ # The global registry is exposed for plugins to register themselves.
27
+ #
28
+ # Sprockets.register_engine '.sass', SassTemplate
29
+ #
30
+ module Engines
31
+ # Returns an `Array` of `Engine`s registered on the
32
+ # `Environment`. If an `ext` argument is supplied, the `Engine`
33
+ # register under that extension will be returned.
34
+ #
35
+ # environment.engines
36
+ # # => [CoffeeScriptTemplate, SassTemplate, ...]
37
+ #
38
+ # environment.engines('.coffee')
39
+ # # => CoffeeScriptTemplate
40
+ #
41
+ def engines(ext = nil)
42
+ if ext
43
+ ext = Sprockets::Utils.normalize_extension(ext)
44
+ @engines[ext]
45
+ else
46
+ @engines.dup
47
+ end
48
+ end
49
+
50
+ # Returns an `Array` of engine extension `String`s.
51
+ #
52
+ # environment.engine_extensions
53
+ # # => ['.coffee', '.sass', ...]
54
+ def engine_extensions
55
+ @engines.keys
56
+ end
57
+
58
+ # Registers a new Engine `klass` for `ext`. If the `ext` already
59
+ # has an engine registered, it will be overridden.
60
+ #
61
+ # environment.register_engine '.coffee', CoffeeScriptTemplate
62
+ #
63
+ def register_engine(ext, klass)
64
+ ext = Sprockets::Utils.normalize_extension(ext)
65
+ @engines[ext] = klass
66
+ end
67
+
68
+ private
69
+ def deep_copy_hash(hash)
70
+ initial = Hash.new { |h, k| h[k] = [] }
71
+ hash.inject(initial) { |h, (k, a)| h[k] = a.dup; h }
72
+ end
73
+ end
74
+
75
+ # Extend Sprockets module to provide global registry
76
+ extend Engines
77
+ @engines = {}
78
+
79
+ # Cherry pick the default Tilt engines that make sense for
80
+ # Sprockets. We don't need ones that only generate html like HAML.
81
+
82
+ # Mmm, CoffeeScript
83
+ register_engine '.coffee', Tilt::CoffeeScriptTemplate
84
+
85
+ # JST engines
86
+ register_engine '.jst', JstProcessor
87
+ register_engine '.eco', EcoTemplate
88
+ register_engine '.ejs', EjsTemplate
89
+
90
+ # CSS engines
91
+ register_engine '.less', Tilt::LessTemplate
92
+ register_engine '.sass', Tilt::SassTemplate
93
+ register_engine '.scss', Tilt::ScssTemplate
94
+
95
+ # Other
96
+ register_engine '.erb', Tilt::ERBTemplate
97
+ register_engine '.str', Tilt::StringTemplate
98
+ end
@@ -1,52 +1,93 @@
1
+ require 'sprockets/base'
2
+ require 'sprockets/charset_normalizer'
3
+ require 'sprockets/context'
4
+ require 'sprockets/directive_processor'
5
+ require 'sprockets/index'
6
+ require 'sprockets/safety_colons'
7
+
8
+ require 'hike'
9
+ require 'logger'
10
+ require 'pathname'
11
+ require 'tilt'
12
+
1
13
  module Sprockets
2
- class Environment
3
- attr_reader :root, :load_path
4
-
5
- def initialize(root, load_path = [])
6
- @load_path = [@root = Pathname.new(self, root)]
7
-
8
- load_path.reverse_each do |location|
9
- register_load_location(location)
14
+ class Environment < Base
15
+ # `Environment` should initialized with your application's root
16
+ # directory. This should be the same as your Rails or Rack root.
17
+ #
18
+ # env = Environment.new(Rails.root)
19
+ #
20
+ def initialize(root = ".")
21
+ @trail = Hike::Trail.new(root)
22
+
23
+ self.logger = Logger.new($stderr)
24
+ self.logger.level = Logger::FATAL
25
+
26
+ # Create a safe `Context` subclass to mutate
27
+ @context_class = Class.new(Context)
28
+
29
+ # Set MD5 as the default digest
30
+ require 'digest/md5'
31
+ @digest_class = ::Digest::MD5
32
+ @version = ''
33
+
34
+ @mime_types = {}
35
+ @engines = Sprockets.engines
36
+ @preprocessors = Hash.new { |h, k| h[k] = [] }
37
+ @postprocessors = Hash.new { |h, k| h[k] = [] }
38
+ @bundle_processors = Hash.new { |h, k| h[k] = [] }
39
+
40
+ @engines.each do |ext, klass|
41
+ add_engine_to_trail(ext, klass)
10
42
  end
11
- end
12
-
13
- def pathname_from(location)
14
- Pathname.new(self, absolute_location_from(location))
15
- end
16
43
 
17
- def register_load_location(location)
18
- pathname = pathname_from(location)
19
- load_path.delete(pathname)
20
- load_path.unshift(pathname)
21
- location
44
+ register_mime_type 'text/css', '.css'
45
+ register_mime_type 'application/javascript', '.js'
46
+
47
+ register_preprocessor 'text/css', DirectiveProcessor
48
+ register_preprocessor 'application/javascript', DirectiveProcessor
49
+
50
+ register_postprocessor 'application/javascript', SafetyColons
51
+ register_bundle_processor 'text/css', CharsetNormalizer
52
+
53
+ expire_index!
54
+
55
+ yield self if block_given?
22
56
  end
23
-
24
- def find(location)
25
- if Sprockets.absolute?(location) && File.exists?(location)
26
- pathname_from(location)
27
- else
28
- find_all(location).first
29
- end
57
+
58
+ # Returns a cached version of the environment.
59
+ #
60
+ # All its file system calls are cached which makes `index` much
61
+ # faster. This behavior is ideal in production since the file
62
+ # system only changes between deploys.
63
+ def index
64
+ Index.new(self)
30
65
  end
31
-
32
- def constants(reload = false)
33
- @constants = nil if reload
34
- @constants ||= find_all("constants.yml").inject({}) do |constants, pathname|
35
- contents = YAML.load(pathname.contents) rescue nil
36
- contents = {} unless contents.is_a?(Hash)
37
- constants.merge(contents)
66
+
67
+ # Cache `find_asset` calls
68
+ def find_asset(path, options = {})
69
+ # Ensure inmemory cached assets are still fresh on every lookup
70
+ if (asset = @assets[path.to_s]) && asset.fresh?
71
+ asset
72
+ elsif asset = super
73
+ @assets[path.to_s] = @assets[asset.pathname.to_s] = asset
74
+ asset
38
75
  end
39
76
  end
40
-
77
+
41
78
  protected
42
- def absolute_location_from(location)
43
- location = location.to_s
44
- location = File.join(root.absolute_location, location) unless Sprockets.absolute?(location)
45
- File.expand_path(location)
79
+ # Cache asset building in persisted cache.
80
+ def build_asset(path, pathname, options)
81
+ # Persisted cache
82
+ cache_asset(pathname.to_s) do
83
+ super
84
+ end
46
85
  end
47
-
48
- def find_all(location)
49
- load_path.map { |pathname| pathname.find(location) }.compact
86
+
87
+ def expire_index!
88
+ # Clear digest to be recomputed
89
+ @digest = nil
90
+ @assets = {}
50
91
  end
51
92
  end
52
93
  end
@@ -0,0 +1,17 @@
1
+ # Define some basic Sprockets error classes
2
+ module Sprockets
3
+ class Error < StandardError; end
4
+ class ArgumentError < Error; end
5
+ class CircularDependencyError < Error; end
6
+ class ContentTypeMismatch < Error; end
7
+ class EncodingError < Error; end
8
+ class FileNotFound < Error; end
9
+
10
+ module EngineError
11
+ attr_accessor :sprockets_annotation
12
+
13
+ def message
14
+ [super, sprockets_annotation].compact.join("\n")
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,79 @@
1
+ require 'sprockets/base'
2
+
3
+ module Sprockets
4
+ # `Index` is a special cached version of `Environment`.
5
+ #
6
+ # The expection is that all of its file system methods are cached
7
+ # for the instances lifetime. This makes `Index` much faster. This
8
+ # behavior is ideal in production environments where the file system
9
+ # is immutable.
10
+ #
11
+ # `Index` should not be initialized directly. Instead use
12
+ # `Environment#index`.
13
+ class Index < Base
14
+ def initialize(environment)
15
+ # Copy environment attributes
16
+ @logger = environment.logger
17
+ @context_class = environment.context_class
18
+ @cache = environment.cache
19
+ @trail = environment.trail.index
20
+ @digest = environment.digest
21
+ @digest_class = environment.digest_class
22
+ @version = environment.version
23
+ @mime_types = environment.mime_types
24
+ @engines = environment.engines
25
+ @preprocessors = environment.preprocessors
26
+ @postprocessors = environment.postprocessors
27
+ @bundle_processors = environment.bundle_processors
28
+
29
+ # Initialize caches
30
+ @assets = {}
31
+ @digests = {}
32
+ end
33
+
34
+ # No-op return self as index
35
+ def index
36
+ self
37
+ end
38
+
39
+ # Cache calls to `file_digest`
40
+ def file_digest(pathname, data = nil)
41
+ memoize(@digests, pathname.to_s) { super }
42
+ end
43
+
44
+ # Cache `find_asset` calls
45
+ def find_asset(path, options = {})
46
+ if asset = @assets[path.to_s]
47
+ asset
48
+ elsif asset = super
49
+ # Cache at logical path and expanded path
50
+ @assets[path.to_s] = @assets[asset.pathname.to_s] = asset
51
+ asset
52
+ end
53
+ end
54
+
55
+ protected
56
+ # Index is immutable, any methods that try to clear the cache
57
+ # should bomb.
58
+ def expire_index!
59
+ raise TypeError, "can't modify immutable index"
60
+ end
61
+
62
+ # Cache asset building in memory and in persisted cache.
63
+ def build_asset(path, pathname, options)
64
+ # Memory cache
65
+ memoize(@assets, pathname.to_s) do
66
+ # Persisted cache
67
+ cache_asset(pathname.to_s) do
68
+ super
69
+ end
70
+ end
71
+ end
72
+
73
+ private
74
+ # Simple memoize helper that stores `nil` values
75
+ def memoize(hash, key)
76
+ hash.key?(key) ? hash[key] : hash[key] = yield
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,26 @@
1
+ require 'tilt'
2
+
3
+ module Sprockets
4
+ class JstProcessor < Tilt::Template
5
+ def self.default_mime_type
6
+ 'application/javascript'
7
+ end
8
+
9
+ def prepare
10
+ end
11
+
12
+ def evaluate(scope, locals, &block)
13
+ <<-JST
14
+ (function() {
15
+ this.JST || (this.JST = {});
16
+ this.JST[#{scope.logical_path.inspect}] = #{indent(data)};
17
+ }).call(this);
18
+ JST
19
+ end
20
+
21
+ private
22
+ def indent(string)
23
+ string.gsub(/$(.)/m, "\\1 ").strip
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,38 @@
1
+ require 'rack/mime'
2
+
3
+ module Sprockets
4
+ module Mime
5
+ # Returns a `Hash` of registered mime types registered on the
6
+ # environment and those part of `Rack::Mime`.
7
+ #
8
+ # If an `ext` is given, it will lookup the mime type for that extension.
9
+ def mime_types(ext = nil)
10
+ if ext.nil?
11
+ Rack::Mime::MIME_TYPES.merge(@mime_types)
12
+ else
13
+ ext = Sprockets::Utils.normalize_extension(ext)
14
+ @mime_types[ext] || Rack::Mime::MIME_TYPES[ext]
15
+ end
16
+ end
17
+
18
+ if {}.respond_to?(:key)
19
+ def extension_for_mime_type(type)
20
+ mime_types.key(type)
21
+ end
22
+ else
23
+ def extension_for_mime_type(type)
24
+ mime_types.index(type)
25
+ end
26
+ end
27
+
28
+ # Register a new mime type.
29
+ def register_mime_type(mime_type, ext)
30
+ ext = Sprockets::Utils.normalize_extension(ext)
31
+ @mime_types[ext] = mime_type
32
+ end
33
+ end
34
+
35
+ # Extend Sprockets module to provide global registry
36
+ extend Mime
37
+ @mime_types = {}
38
+ end
@@ -0,0 +1,280 @@
1
+ require 'sprockets/engines'
2
+ require 'sprockets/mime'
3
+ require 'sprockets/processor'
4
+ require 'sprockets/utils'
5
+
6
+ module Sprockets
7
+ # `Processing` is an internal mixin whose public methods are exposed on
8
+ # the `Environment` and `Index` classes.
9
+ module Processing
10
+ include Engines, Mime
11
+
12
+ # Register a new mime type.
13
+ def register_mime_type(mime_type, ext)
14
+ # Overrides the global behavior to expire the index
15
+ expire_index!
16
+ @trail.append_extension(ext)
17
+ super
18
+ end
19
+
20
+ # Returns an `Array` of format extension `String`s.
21
+ #
22
+ # format_extensions
23
+ # # => ['.js', '.css']
24
+ #
25
+ def format_extensions
26
+ @trail.extensions - @engines.keys
27
+ end
28
+
29
+ # Registers a new Engine `klass` for `ext`.
30
+ def register_engine(ext, klass)
31
+ # Overrides the global behavior to expire the index
32
+ expire_index!
33
+ add_engine_to_trail(ext, klass)
34
+ super
35
+ end
36
+
37
+ # Deprecated alias for `preprocessors`.
38
+ def processors(*args)
39
+ preprocessors(*args)
40
+ end
41
+
42
+ # Returns an `Array` of `Processor` classes. If a `mime_type`
43
+ # argument is supplied, the processors registered under that
44
+ # extension will be returned.
45
+ #
46
+ # Preprocessors are ran before Postprocessors and Engine
47
+ # processors.
48
+ #
49
+ # All `Processor`s must follow the `Tilt::Template` interface. It is
50
+ # recommended to subclass `Tilt::Template`.
51
+ def preprocessors(mime_type = nil)
52
+ if mime_type
53
+ @preprocessors[mime_type].dup
54
+ else
55
+ deep_copy_hash(@preprocessors)
56
+ end
57
+ end
58
+
59
+ # Returns an `Array` of `Processor` classes. If a `mime_type`
60
+ # argument is supplied, the processors registered under that
61
+ # extension will be returned.
62
+ #
63
+ # Postprocessors are ran after Postprocessors and Engine processors.
64
+ #
65
+ # All `Processor`s must follow the `Tilt::Template` interface. It is
66
+ # recommended to subclass `Tilt::Template`.
67
+ def postprocessors(mime_type = nil)
68
+ if mime_type
69
+ @postprocessors[mime_type].dup
70
+ else
71
+ deep_copy_hash(@postprocessors)
72
+ end
73
+ end
74
+
75
+ # Deprecated alias for `register_preprocessor`.
76
+ def register_processor(*args, &block)
77
+ register_preprocessor(*args, &block)
78
+ end
79
+
80
+ # Registers a new Preprocessor `klass` for `mime_type`.
81
+ #
82
+ # register_preprocessor 'text/css', Sprockets::DirectiveProcessor
83
+ #
84
+ # A block can be passed for to create a shorthand processor.
85
+ #
86
+ # register_preprocessor :my_processor do |context, data|
87
+ # data.gsub(...)
88
+ # end
89
+ #
90
+ def register_preprocessor(mime_type, klass, &block)
91
+ expire_index!
92
+
93
+ if block_given?
94
+ name = klass.to_s
95
+ klass = Class.new(Processor) do
96
+ @name = name
97
+ @processor = block
98
+ end
99
+ end
100
+
101
+ @preprocessors[mime_type].push(klass)
102
+ end
103
+
104
+ # Registers a new Postprocessor `klass` for `mime_type`.
105
+ #
106
+ # register_postprocessor 'text/css', Sprockets::CharsetNormalizer
107
+ #
108
+ # A block can be passed for to create a shorthand processor.
109
+ #
110
+ # register_postprocessor :my_processor do |context, data|
111
+ # data.gsub(...)
112
+ # end
113
+ #
114
+ def register_postprocessor(mime_type, klass, &block)
115
+ expire_index!
116
+
117
+ if block_given?
118
+ name = klass.to_s
119
+ klass = Class.new(Processor) do
120
+ @name = name
121
+ @processor = block
122
+ end
123
+ end
124
+
125
+ @postprocessors[mime_type].push(klass)
126
+ end
127
+
128
+ # Deprecated alias for `unregister_preprocessor`.
129
+ def unregister_processor(*args)
130
+ unregister_preprocessor(*args)
131
+ end
132
+
133
+ # Remove Preprocessor `klass` for `mime_type`.
134
+ #
135
+ # unregister_preprocessor 'text/css', Sprockets::DirectiveProcessor
136
+ #
137
+ def unregister_preprocessor(mime_type, klass)
138
+ expire_index!
139
+
140
+ if klass.is_a?(String) || klass.is_a?(Symbol)
141
+ klass = @preprocessors[mime_type].detect { |cls|
142
+ cls.respond_to?(:name) &&
143
+ cls.name == "Sprockets::Processor (#{klass})"
144
+ }
145
+ end
146
+
147
+ @preprocessors[mime_type].delete(klass)
148
+ end
149
+
150
+ # Remove Postprocessor `klass` for `mime_type`.
151
+ #
152
+ # unregister_postprocessor 'text/css', Sprockets::DirectiveProcessor
153
+ #
154
+ def unregister_postprocessor(mime_type, klass)
155
+ expire_index!
156
+
157
+ if klass.is_a?(String) || klass.is_a?(Symbol)
158
+ klass = @postprocessors[mime_type].detect { |cls|
159
+ cls.respond_to?(:name) &&
160
+ cls.name == "Sprockets::Processor (#{klass})"
161
+ }
162
+ end
163
+
164
+ @postprocessors[mime_type].delete(klass)
165
+ end
166
+
167
+ # Returns an `Array` of `Processor` classes. If a `mime_type`
168
+ # argument is supplied, the processors registered under that
169
+ # extension will be returned.
170
+ #
171
+ # Bundle Processors are ran on concatenated assets rather than
172
+ # individual files.
173
+ #
174
+ # All `Processor`s must follow the `Tilt::Template` interface. It is
175
+ # recommended to subclass `Tilt::Template`.
176
+ def bundle_processors(mime_type = nil)
177
+ if mime_type
178
+ @bundle_processors[mime_type].dup
179
+ else
180
+ deep_copy_hash(@bundle_processors)
181
+ end
182
+ end
183
+
184
+ # Registers a new Bundle Processor `klass` for `mime_type`.
185
+ #
186
+ # register_bundle_processor 'text/css', Sprockets::CharsetNormalizer
187
+ #
188
+ # A block can be passed for to create a shorthand processor.
189
+ #
190
+ # register_bundle_processor :my_processor do |context, data|
191
+ # data.gsub(...)
192
+ # end
193
+ #
194
+ def register_bundle_processor(mime_type, klass, &block)
195
+ expire_index!
196
+
197
+ if block_given?
198
+ name = klass.to_s
199
+ klass = Class.new(Processor) do
200
+ @name = name
201
+ @processor = block
202
+ end
203
+ end
204
+
205
+ @bundle_processors[mime_type].push(klass)
206
+ end
207
+
208
+ # Remove Bundle Processor `klass` for `mime_type`.
209
+ #
210
+ # unregister_bundle_processor 'text/css', Sprockets::CharsetNormalizer
211
+ #
212
+ def unregister_bundle_processor(mime_type, klass)
213
+ expire_index!
214
+
215
+ if klass.is_a?(String) || klass.is_a?(Symbol)
216
+ klass = @bundle_processors[mime_type].detect { |cls|
217
+ cls.respond_to?(:name) &&
218
+ cls.name == "Sprockets::Processor (#{klass})"
219
+ }
220
+ end
221
+
222
+ @bundle_processors[mime_type].delete(klass)
223
+ end
224
+
225
+ # Return CSS compressor or nil if none is set
226
+ def css_compressor
227
+ bundle_processors('text/css').detect { |klass|
228
+ klass.respond_to?(:name) &&
229
+ klass.name == 'Sprockets::Processor (css_compressor)'
230
+ }
231
+ end
232
+
233
+ # Assign a compressor to run on `text/css` assets.
234
+ #
235
+ # The compressor object must respond to `compress` or `compile`.
236
+ def css_compressor=(compressor)
237
+ expire_index!
238
+
239
+ unregister_bundle_processor 'text/css', :css_compressor
240
+ return unless compressor
241
+
242
+ register_bundle_processor 'text/css', :css_compressor do |context, data|
243
+ compressor.compress(data)
244
+ end
245
+ end
246
+
247
+ # Return JS compressor or nil if none is set
248
+ def js_compressor
249
+ bundle_processors('application/javascript').detect { |klass|
250
+ klass.respond_to?(:name) &&
251
+ klass.name == 'Sprockets::Processor (js_compressor)'
252
+ }
253
+ end
254
+
255
+ # Assign a compressor to run on `application/javascript` assets.
256
+ #
257
+ # The compressor object must respond to `compress` or `compile`.
258
+ def js_compressor=(compressor)
259
+ expire_index!
260
+
261
+ unregister_bundle_processor 'application/javascript', :js_compressor
262
+ return unless compressor
263
+
264
+ register_bundle_processor 'application/javascript', :js_compressor do |context, data|
265
+ compressor.compress(data)
266
+ end
267
+ end
268
+
269
+ private
270
+ def add_engine_to_trail(ext, klass)
271
+ @trail.append_extension(ext.to_s)
272
+
273
+ if klass.respond_to?(:default_mime_type) && klass.default_mime_type
274
+ if format_ext = extension_for_mime_type(klass.default_mime_type)
275
+ @trail.alias_extension(ext.to_s, format_ext)
276
+ end
277
+ end
278
+ end
279
+ end
280
+ end