sprockets 3.7.2 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -261
  3. data/{LICENSE → MIT-LICENSE} +2 -2
  4. data/README.md +527 -320
  5. data/bin/sprockets +11 -7
  6. data/lib/rake/sprocketstask.rb +9 -4
  7. data/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
  8. data/lib/sprockets/asset.rb +39 -27
  9. data/lib/sprockets/autoload/babel.rb +8 -0
  10. data/lib/sprockets/autoload/closure.rb +1 -0
  11. data/lib/sprockets/autoload/coffee_script.rb +1 -0
  12. data/lib/sprockets/autoload/eco.rb +1 -0
  13. data/lib/sprockets/autoload/ejs.rb +1 -0
  14. data/lib/sprockets/autoload/jsminc.rb +8 -0
  15. data/lib/sprockets/autoload/sass.rb +1 -0
  16. data/lib/sprockets/autoload/sassc.rb +8 -0
  17. data/lib/sprockets/autoload/uglifier.rb +1 -0
  18. data/lib/sprockets/autoload/yui.rb +1 -0
  19. data/lib/sprockets/autoload/zopfli.rb +7 -0
  20. data/lib/sprockets/autoload.rb +5 -0
  21. data/lib/sprockets/babel_processor.rb +66 -0
  22. data/lib/sprockets/base.rb +49 -12
  23. data/lib/sprockets/bower.rb +6 -3
  24. data/lib/sprockets/bundle.rb +41 -5
  25. data/lib/sprockets/cache/file_store.rb +25 -3
  26. data/lib/sprockets/cache/memory_store.rb +28 -10
  27. data/lib/sprockets/cache/null_store.rb +8 -0
  28. data/lib/sprockets/cache.rb +37 -2
  29. data/lib/sprockets/cached_environment.rb +15 -20
  30. data/lib/sprockets/closure_compressor.rb +1 -0
  31. data/lib/sprockets/coffee_script_processor.rb +19 -5
  32. data/lib/sprockets/compressing.rb +43 -3
  33. data/lib/sprockets/configuration.rb +5 -9
  34. data/lib/sprockets/context.rb +99 -25
  35. data/lib/sprockets/dependencies.rb +2 -1
  36. data/lib/sprockets/digest_utils.rb +35 -18
  37. data/lib/sprockets/directive_processor.rb +64 -36
  38. data/lib/sprockets/eco_processor.rb +2 -1
  39. data/lib/sprockets/ejs_processor.rb +2 -1
  40. data/lib/sprockets/encoding_utils.rb +1 -0
  41. data/lib/sprockets/environment.rb +9 -4
  42. data/lib/sprockets/erb_processor.rb +34 -21
  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 +88 -68
  54. data/lib/sprockets/manifest.rb +67 -64
  55. data/lib/sprockets/manifest_utils.rb +9 -6
  56. data/lib/sprockets/mime.rb +8 -42
  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 +52 -39
  74. data/lib/sprockets/source_map_processor.rb +66 -0
  75. data/lib/sprockets/source_map_utils.rb +483 -0
  76. data/lib/sprockets/transformers.rb +63 -35
  77. data/lib/sprockets/uglifier_compressor.rb +21 -11
  78. data/lib/sprockets/unloaded_asset.rb +13 -11
  79. data/lib/sprockets/uri_tar.rb +1 -0
  80. data/lib/sprockets/uri_utils.rb +12 -9
  81. data/lib/sprockets/utils/gzip.rb +46 -14
  82. data/lib/sprockets/utils.rb +64 -89
  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 +139 -34
  87. data/lib/sprockets/coffee_script_template.rb +0 -17
  88. data/lib/sprockets/deprecation.rb +0 -90
  89. data/lib/sprockets/eco_template.rb +0 -17
  90. data/lib/sprockets/ejs_template.rb +0 -17
  91. data/lib/sprockets/engines.rb +0 -92
  92. data/lib/sprockets/erb_template.rb +0 -11
  93. data/lib/sprockets/legacy.rb +0 -330
  94. data/lib/sprockets/legacy_proc_processor.rb +0 -35
  95. data/lib/sprockets/legacy_tilt_processor.rb +0 -29
  96. data/lib/sprockets/sass_template.rb +0 -19
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
1
2
  require 'set'
2
3
  require 'sprockets/utils'
4
+ require 'sprockets/uri_utils'
3
5
 
4
6
  module Sprockets
5
7
  # Internal: Bundle processor takes a single file asset and prepends all the
@@ -8,22 +10,39 @@ module Sprockets
8
10
  # Uses pipeline metadata:
9
11
  #
10
12
  # :required - Ordered Set of asset URIs to prepend
11
- # :stubbed - Set of asset URIs to substract from the required set.
13
+ # :stubbed - Set of asset URIs to subtract from the required set.
12
14
  #
13
15
  # Also see DirectiveProcessor.
14
16
  class Bundle
15
17
  def self.call(input)
16
18
  env = input[:environment]
17
19
  type = input[:content_type]
20
+ input[:links] ||= Set.new
18
21
  dependencies = Set.new(input[:metadata][:dependencies])
19
22
 
20
- processed_uri, deps = env.resolve(input[:filename], accept: type, pipeline: :self, compat: false)
23
+ processed_uri, deps = env.resolve(input[:filename], accept: type, pipeline: :self)
21
24
  dependencies.merge(deps)
22
25
 
26
+ # DirectiveProcessor (and any other transformers called here with pipeline=self)
27
+ primary_asset = env.load(processed_uri)
28
+ to_load = primary_asset.metadata.delete(:to_load) || Set.new
29
+ to_link = primary_asset.metadata.delete(:to_link) || Set.new
30
+
31
+ to_load.each do |uri|
32
+ loaded_asset = env.load(uri)
33
+ dependencies.merge(loaded_asset.metadata[:dependencies])
34
+ if to_link.include?(uri)
35
+ primary_metadata = primary_asset.metadata
36
+ input[:links] << loaded_asset.uri
37
+ primary_metadata[:links] << loaded_asset.uri
38
+ end
39
+ end
40
+
23
41
  find_required = proc { |uri| env.load(uri).metadata[:required] }
24
42
  required = Utils.dfs(processed_uri, &find_required)
25
43
  stubbed = Utils.dfs(env.load(processed_uri).metadata[:stubbed], &find_required)
26
44
  required.subtract(stubbed)
45
+ dedup(required)
27
46
  assets = required.map { |uri| env.load(uri) }
28
47
 
29
48
  (required + stubbed).each do |uri|
@@ -31,21 +50,38 @@ module Sprockets
31
50
  end
32
51
 
33
52
  reducers = Hash[env.match_mime_type_keys(env.config[:bundle_reducers], type).flat_map(&:to_a)]
34
- process_bundle_reducers(assets, reducers).merge(dependencies: dependencies, included: assets.map(&:uri))
53
+ process_bundle_reducers(input, assets, reducers).merge(dependencies: dependencies, included: assets.map(&:uri))
54
+ end
55
+
56
+ # Internal: Removes uri from required if it's already included as an alias.
57
+ #
58
+ # required - Set of required uris
59
+ #
60
+ # Returns deduped set of uris
61
+ def self.dedup(required)
62
+ dupes = required.reduce([]) do |r, uri|
63
+ path, params = URIUtils.parse_asset_uri(uri)
64
+ if (params.delete(:index_alias))
65
+ r << URIUtils.build_asset_uri(path, params)
66
+ end
67
+ r
68
+ end
69
+ required.subtract(dupes)
35
70
  end
36
71
 
37
72
  # Internal: Run bundle reducers on set of Assets producing a reduced
38
73
  # metadata Hash.
39
74
  #
75
+ # filename - String bundle filename
40
76
  # assets - Array of Assets
41
77
  # reducers - Array of [initial, reducer_proc] pairs
42
78
  #
43
79
  # Returns reduced asset metadata Hash.
44
- def self.process_bundle_reducers(assets, reducers)
80
+ def self.process_bundle_reducers(input, assets, reducers)
45
81
  initial = {}
46
82
  reducers.each do |k, (v, _)|
47
83
  if v.respond_to?(:call)
48
- initial[k] = v.call
84
+ initial[k] = v.call(input)
49
85
  elsif !v.nil?
50
86
  initial[k] = v
51
87
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'fileutils'
2
3
  require 'logger'
3
4
  require 'sprockets/encoding_utils'
@@ -19,7 +20,9 @@ module Sprockets
19
20
  class FileStore
20
21
  # Internal: Default key limit for store.
21
22
  DEFAULT_MAX_SIZE = 25 * 1024 * 1024
22
-
23
+ EXCLUDED_DIRS = ['.', '..'].freeze
24
+ GITKEEP_FILES = ['.gitkeep', '.keep'].freeze
25
+
23
26
  # Internal: Default standard error fatal logger.
24
27
  #
25
28
  # Returns a Logger.
@@ -32,8 +35,10 @@ module Sprockets
32
35
  # Public: Initialize the cache store.
33
36
  #
34
37
  # root - A String path to a directory to persist cached values to.
35
- # max_size - A Integer of the maximum number of keys the store will hold.
36
- # (default: 1000).
38
+ # max_size - A Integer of the maximum size the store will hold (in bytes).
39
+ # (default: 25MB).
40
+ # logger - The logger to which some info will be printed.
41
+ # (default logger level is FATAL and won't output anything).
37
42
  def initialize(root, max_size = DEFAULT_MAX_SIZE, logger = self.class.default_logger)
38
43
  @root = root
39
44
  @max_size = max_size
@@ -122,6 +127,23 @@ module Sprockets
122
127
  "#<#{self.class} size=#{size}/#{@max_size}>"
123
128
  end
124
129
 
130
+ # Public: Clear the cache
131
+ #
132
+ # adapted from ActiveSupport::Cache::FileStore#clear
133
+ #
134
+ # Deletes all items from the cache. In this case it deletes all the entries in the specified
135
+ # file store directory except for .keep or .gitkeep. Be careful which directory is specified
136
+ # as @root because everything in that directory will be deleted.
137
+ #
138
+ # Returns true
139
+ def clear(options=nil)
140
+ if File.exist?(@root)
141
+ root_dirs = Dir.entries(@root).reject { |f| (EXCLUDED_DIRS + GITKEEP_FILES).include?(f) }
142
+ FileUtils.rm_r(root_dirs.collect{ |f| File.join(@root, f) })
143
+ end
144
+ true
145
+ end
146
+
125
147
  private
126
148
  # Internal: Get all cache files along with stats.
127
149
  #
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Sprockets
2
3
  class Cache
3
4
  # Public: Basic in memory LRU cache.
@@ -21,6 +22,7 @@ module Sprockets
21
22
  def initialize(max_size = DEFAULT_MAX_SIZE)
22
23
  @max_size = max_size
23
24
  @cache = {}
25
+ @mutex = Mutex.new
24
26
  end
25
27
 
26
28
  # Public: Retrieve value from cache.
@@ -31,12 +33,14 @@ module Sprockets
31
33
  #
32
34
  # Returns Object or nil or the value is not set.
33
35
  def get(key)
34
- exists = true
35
- value = @cache.delete(key) { exists = false }
36
- if exists
37
- @cache[key] = value
38
- else
39
- nil
36
+ @mutex.synchronize do
37
+ exists = true
38
+ value = @cache.delete(key) { exists = false }
39
+ if exists
40
+ @cache[key] = value
41
+ else
42
+ nil
43
+ end
40
44
  end
41
45
  end
42
46
 
@@ -49,9 +53,11 @@ module Sprockets
49
53
  #
50
54
  # Returns Object value.
51
55
  def set(key, value)
52
- @cache.delete(key)
53
- @cache[key] = value
54
- @cache.shift if @cache.size > @max_size
56
+ @mutex.synchronize do
57
+ @cache.delete(key)
58
+ @cache[key] = value
59
+ @cache.shift if @cache.size > @max_size
60
+ end
55
61
  value
56
62
  end
57
63
 
@@ -59,7 +65,19 @@ module Sprockets
59
65
  #
60
66
  # Returns String.
61
67
  def inspect
62
- "#<#{self.class} size=#{@cache.size}/#{@max_size}>"
68
+ @mutex.synchronize do
69
+ "#<#{self.class} size=#{@cache.size}/#{@max_size}>"
70
+ end
71
+ end
72
+
73
+ # Public: Clear the cache
74
+ #
75
+ # Returns true
76
+ def clear(options=nil)
77
+ @mutex.synchronize do
78
+ @cache.clear
79
+ end
80
+ true
63
81
  end
64
82
  end
65
83
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Sprockets
2
3
  class Cache
3
4
  # Public: A compatible cache store that doesn't store anything. Used by
@@ -41,6 +42,13 @@ module Sprockets
41
42
  def inspect
42
43
  "#<#{self.class}>"
43
44
  end
45
+
46
+ # Public: Simulate clearing the cache
47
+ #
48
+ # Returns true
49
+ def clear(options=nil)
50
+ true
51
+ end
44
52
  end
45
53
  end
46
54
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'logger'
2
3
  require 'sprockets/digest_utils'
3
4
 
@@ -35,6 +36,12 @@ module Sprockets
35
36
  #
36
37
  # Returns argument value.
37
38
  #
39
+ # clear(options)
40
+ #
41
+ # Clear the entire cache. Be careful with this method since it could
42
+ # affect other processes if shared cache is being used.
43
+ #
44
+ # The options hash is passed to the underlying cache implementation.
38
45
  class Cache
39
46
  # Builtin cache stores.
40
47
  autoload :FileStore, 'sprockets/cache/file_store'
@@ -44,7 +51,7 @@ module Sprockets
44
51
  # Internal: Cache key version for this class. Rarely should have to change
45
52
  # unless the cache format radically changes. Will be bump on major version
46
53
  # releases though.
47
- VERSION = '3.0'
54
+ VERSION = '4.0.0'
48
55
 
49
56
  def self.default_logger
50
57
  logger = Logger.new($stderr)
@@ -55,7 +62,7 @@ module Sprockets
55
62
  # Internal: Wrap a backend cache store.
56
63
  #
57
64
  # Always assign a backend cache store instance to Environment#cache= and
58
- # use Environment#cache to retreive a wrapped interface.
65
+ # use Environment#cache to retrieve a wrapped interface.
59
66
  #
60
67
  # cache - A compatible backend cache store instance.
61
68
  def initialize(cache = nil, logger = self.class.default_logger)
@@ -143,6 +150,14 @@ module Sprockets
143
150
  "#<#{self.class} local=#{@fetch_cache.inspect} store=#{@cache_wrapper.cache.inspect}>"
144
151
  end
145
152
 
153
+ # Public: Clear cache
154
+ #
155
+ # Returns truthy on success, potentially raises exception on failure
156
+ def clear(options=nil)
157
+ @cache_wrapper.clear
158
+ @fetch_cache.clear
159
+ end
160
+
146
161
  private
147
162
  # Internal: Expand object cache key into a short String key.
148
163
  #
@@ -211,6 +226,16 @@ module Sprockets
211
226
  def set(key, value)
212
227
  cache.set(key, value)
213
228
  end
229
+
230
+ def clear(options=nil)
231
+ # dalli has a #flush method so try it
232
+ if cache.respond_to?(:flush)
233
+ cache.flush(options)
234
+ else
235
+ cache.clear(options)
236
+ end
237
+ true
238
+ end
214
239
  end
215
240
 
216
241
  class HashWrapper < Wrapper
@@ -221,6 +246,11 @@ module Sprockets
221
246
  def set(key, value)
222
247
  cache[key] = value
223
248
  end
249
+
250
+ def clear(options=nil)
251
+ cache.clear
252
+ true
253
+ end
224
254
  end
225
255
 
226
256
  class ReadWriteWrapper < Wrapper
@@ -231,6 +261,11 @@ module Sprockets
231
261
  def set(key, value)
232
262
  cache.write(key, value)
233
263
  end
264
+
265
+ def clear(options=nil)
266
+ cache.clear(options)
267
+ true
268
+ end
234
269
  end
235
270
  end
236
271
  end
@@ -1,26 +1,26 @@
1
+ # frozen_string_literal: true
1
2
  require 'sprockets/base'
2
3
 
3
4
  module Sprockets
4
- # `Cached` is a special cached version of `Environment`.
5
+ # `CachedEnvironment` is a special cached version of `Environment`.
5
6
  #
6
- # The expection is that all of its file system methods are cached
7
- # for the instances lifetime. This makes `Cached` much faster. This
7
+ # The exception is that all of its file system methods are cached
8
+ # for the instances lifetime. This makes `CachedEnvironment` much faster. This
8
9
  # behavior is ideal in production environments where the file system
9
10
  # is immutable.
10
11
  #
11
- # `Cached` should not be initialized directly. Instead use
12
+ # `CachedEnvironment` should not be initialized directly. Instead use
12
13
  # `Environment#cached`.
13
14
  class CachedEnvironment < Base
14
15
  def initialize(environment)
15
16
  initialize_configuration(environment)
16
17
 
17
18
  @cache = environment.cache
18
- @stats = Hash.new { |h, k| h[k] = _stat(k) }
19
- @entries = Hash.new { |h, k| h[k] = _entries(k) }
20
- @uris = Hash.new { |h, k| h[k] = _load(k) }
21
-
22
- @processor_cache_keys = Hash.new { |h, k| h[k] = _processor_cache_key(k) }
23
- @resolved_dependencies = Hash.new { |h, k| h[k] = _resolve_dependency(k) }
19
+ @stats = Concurrent::Map.new
20
+ @entries = Concurrent::Map.new
21
+ @uris = Concurrent::Map.new
22
+ @processor_cache_keys = Concurrent::Map.new
23
+ @resolved_dependencies = Concurrent::Map.new
24
24
  end
25
25
 
26
26
  # No-op return self as cached environment.
@@ -30,33 +30,28 @@ module Sprockets
30
30
  alias_method :index, :cached
31
31
 
32
32
  # Internal: Cache Environment#entries
33
- alias_method :_entries, :entries
34
33
  def entries(path)
35
- @entries[path]
34
+ @entries.fetch_or_store(path) { super(path) }
36
35
  end
37
36
 
38
37
  # Internal: Cache Environment#stat
39
- alias_method :_stat, :stat
40
38
  def stat(path)
41
- @stats[path]
39
+ @stats.fetch_or_store(path) { super(path) }
42
40
  end
43
41
 
44
42
  # Internal: Cache Environment#load
45
- alias_method :_load, :load
46
43
  def load(uri)
47
- @uris[uri]
44
+ @uris.fetch_or_store(uri) { super(uri) }
48
45
  end
49
46
 
50
47
  # Internal: Cache Environment#processor_cache_key
51
- alias_method :_processor_cache_key, :processor_cache_key
52
48
  def processor_cache_key(str)
53
- @processor_cache_keys[str]
49
+ @processor_cache_keys.fetch_or_store(str) { super(str) }
54
50
  end
55
51
 
56
52
  # Internal: Cache Environment#resolve_dependency
57
- alias_method :_resolve_dependency, :resolve_dependency
58
53
  def resolve_dependency(str)
59
- @resolved_dependencies[str]
54
+ @resolved_dependencies.fetch_or_store(str) { super(str) }
60
55
  end
61
56
 
62
57
  private
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'sprockets/autoload'
2
3
  require 'sprockets/digest_utils'
3
4
 
@@ -1,15 +1,17 @@
1
+ # frozen_string_literal: true
1
2
  require 'sprockets/autoload'
3
+ require 'sprockets/source_map_utils'
2
4
 
3
5
  module Sprockets
4
6
  # Processor engine class for the CoffeeScript compiler.
5
7
  # Depends on the `coffee-script` and `coffee-script-source` gems.
6
8
  #
7
- # For more infomation see:
9
+ # For more information see:
8
10
  #
9
- # https://github.com/josh/ruby-coffee-script
11
+ # https://github.com/rails/ruby-coffee-script
10
12
  #
11
13
  module CoffeeScriptProcessor
12
- VERSION = '1'
14
+ VERSION = '2'
13
15
 
14
16
  def self.cache_key
15
17
  @cache_key ||= "#{name}:#{Autoload::CoffeeScript::Source.version}:#{VERSION}".freeze
@@ -17,9 +19,21 @@ module Sprockets
17
19
 
18
20
  def self.call(input)
19
21
  data = input[:data]
20
- input[:cache].fetch([self.cache_key, data]) do
21
- Autoload::CoffeeScript.compile(data)
22
+
23
+ js, map = input[:cache].fetch([self.cache_key, data, input[:filename]]) do
24
+ result = Autoload::CoffeeScript.compile(
25
+ data,
26
+ sourceMap: "v3",
27
+ sourceFiles: [File.basename(input[:filename])],
28
+ generatedFile: input[:filename]
29
+ )
30
+ [result['js'], JSON.parse(result['v3SourceMap'])]
22
31
  end
32
+
33
+ map = SourceMapUtils.format_source_map(map, input)
34
+ map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
35
+
36
+ { data: js, map: map }
23
37
  end
24
38
  end
25
39
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'sprockets/utils'
2
3
 
3
4
  module Sprockets
@@ -10,6 +11,24 @@ module Sprockets
10
11
  config[:compressors]
11
12
  end
12
13
 
14
+ # Public: Register a new compressor `klass` at `sym` for `mime_type`.
15
+ #
16
+ # Registering a processor allows it to be looked up by `sym` later when
17
+ # assigning a JavaScript or CSS compressor.
18
+ #
19
+ # Compressors only operate on JavaScript and CSS. If you want to compress a
20
+ # different type of asset, use a processor instead.
21
+ #
22
+ # Examples
23
+ #
24
+ # register_compressor 'text/css', :my_sass, MySassCompressor
25
+ # css_compressor = :my_sass
26
+ #
27
+ # mime_type - String MIME Type (one of: 'test/css' or 'application/javascript').
28
+ # sym - Symbol registration address.
29
+ # klass - The compressor class.
30
+ #
31
+ # Returns nothing.
13
32
  def register_compressor(mime_type, sym, klass)
14
33
  self.config = hash_reassoc(config, :compressors, mime_type) do |compressors|
15
34
  compressors[sym] = klass
@@ -35,7 +54,7 @@ module Sprockets
35
54
  if compressor.is_a?(Symbol)
36
55
  @css_compressor = klass = config[:compressors]['text/css'][compressor] || raise(Error, "unknown compressor: #{compressor}")
37
56
  elsif compressor.respond_to?(:compress)
38
- klass = LegacyProcProcessor.new(:css_compressor, proc { |context, data| compressor.compress(data) })
57
+ klass = proc { |input| compressor.compress(input[:data]) }
39
58
  @css_compressor = :css_compressor
40
59
  else
41
60
  @css_compressor = klass = compressor
@@ -62,7 +81,7 @@ module Sprockets
62
81
  if compressor.is_a?(Symbol)
63
82
  @js_compressor = klass = config[:compressors]['application/javascript'][compressor] || raise(Error, "unknown compressor: #{compressor}")
64
83
  elsif compressor.respond_to?(:compress)
65
- klass = LegacyProcProcessor.new(:js_compressor, proc { |context, data| compressor.compress(data) })
84
+ klass = proc { |input| compressor.compress(input[:data]) }
66
85
  @js_compressor = :js_compressor
67
86
  else
68
87
  @js_compressor = klass = compressor
@@ -83,12 +102,33 @@ module Sprockets
83
102
 
84
103
  # Public: Enable or disable the creation of Gzip files.
85
104
  #
86
- # Defaults to true.
105
+ # To disable gzip generation set to a falsey value:
87
106
  #
88
107
  # environment.gzip = false
89
108
  #
109
+ # To enable set to a truthy value. By default zlib wil
110
+ # be used to gzip assets. If you have the Zopfli gem
111
+ # installed you can specify the zopfli algorithm to be used
112
+ # instead:
113
+ #
114
+ # environment.gzip = :zopfli
115
+ #
90
116
  def gzip=(gzip)
91
117
  self.config = config.merge(gzip_enabled: gzip).freeze
118
+
119
+ case gzip
120
+ when false, nil
121
+ self.unregister_exporter Exporters::ZlibExporter
122
+ self.unregister_exporter Exporters::ZopfliExporter
123
+ when :zopfli
124
+ self.unregister_exporter Exporters::ZlibExporter
125
+ self.register_exporter '*/*', Exporters::ZopfliExporter
126
+ else
127
+ self.unregister_exporter Exporters::ZopfliExporter
128
+ self.register_exporter '*/*', Exporters::ZlibExporter
129
+ end
130
+
131
+ gzip
92
132
  end
93
133
  end
94
134
  end
@@ -1,27 +1,25 @@
1
+ # frozen_string_literal: true
1
2
  require 'sprockets/compressing'
2
3
  require 'sprockets/dependencies'
3
- require 'sprockets/engines'
4
4
  require 'sprockets/mime'
5
5
  require 'sprockets/paths'
6
6
  require 'sprockets/processing'
7
+ require 'sprockets/exporting'
7
8
  require 'sprockets/transformers'
8
9
  require 'sprockets/utils'
9
10
 
10
11
  module Sprockets
11
12
  module Configuration
12
- include Paths, Mime, Engines, Transformers, Processing, Compressing, Dependencies, Utils
13
+ include Paths, Mime, Transformers, Processing, Exporting, Compressing, Dependencies, Utils
13
14
 
14
15
  def initialize_configuration(parent)
15
16
  @config = parent.config
16
- @computed_config = parent.computed_config
17
17
  @logger = parent.logger
18
18
  @context_class = Class.new(parent.context_class)
19
19
  end
20
20
 
21
21
  attr_reader :config
22
22
 
23
- attr_accessor :computed_config
24
-
25
23
  def config=(config)
26
24
  raise TypeError, "can't assign mutable config" unless config.frozen?
27
25
  @config = config
@@ -61,16 +59,14 @@ module Sprockets
61
59
 
62
60
  # Deprecated: Assign a `Digest` implementation class. This maybe any Ruby
63
61
  # `Digest::` implementation such as `Digest::SHA256` or
64
- # `Digest::MD5`.
62
+ # `Digest::SHA512`.
65
63
  #
66
- # environment.digest_class = Digest::MD5
64
+ # environment.digest_class = Digest::SHA512
67
65
  #
68
66
  def digest_class=(klass)
69
67
  self.config = config.merge(digest_class: klass).freeze
70
68
  end
71
69
 
72
- # Deprecated: Get `Context` class.
73
- #
74
70
  # This class maybe mutated and mixed in with custom helpers.
75
71
  #
76
72
  # environment.context_class.instance_eval do