sprockets 4.0.0.beta3 → 4.0.0.beta4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/bin/sprockets +1 -0
- data/lib/sprockets.rb +13 -1
- data/lib/sprockets/asset.rb +7 -0
- data/lib/sprockets/autoload.rb +2 -1
- data/lib/sprockets/autoload/zopfli.rb +7 -0
- data/lib/sprockets/babel_processor.rb +6 -0
- data/lib/sprockets/base.rb +10 -0
- data/lib/sprockets/compressing.rb +22 -1
- data/lib/sprockets/configuration.rb +2 -1
- data/lib/sprockets/context.rb +31 -0
- data/lib/sprockets/digest_utils.rb +12 -6
- data/lib/sprockets/environment.rb +4 -0
- data/lib/sprockets/erb_processor.rb +24 -23
- data/lib/sprockets/exporters/base.rb +72 -0
- data/lib/sprockets/exporters/file_exporter.rb +24 -0
- data/lib/sprockets/exporters/zlib_exporter.rb +33 -0
- data/lib/sprockets/exporters/zopfli_exporter.rb +14 -0
- data/lib/sprockets/exporting.rb +73 -0
- data/lib/sprockets/loader.rb +1 -1
- data/lib/sprockets/manifest.rb +51 -28
- data/lib/sprockets/path_utils.rb +28 -2
- data/lib/sprockets/processing.rb +2 -2
- data/lib/sprockets/processor_utils.rb +1 -3
- data/lib/sprockets/resolve.rb +3 -0
- data/lib/sprockets/sass_processor.rb +6 -3
- data/lib/sprockets/sassc_processor.rb +16 -12
- data/lib/sprockets/source_map_comment_processor.rb +3 -1
- data/lib/sprockets/source_map_processor.rb +5 -4
- data/lib/sprockets/source_map_utils.rb +6 -1
- data/lib/sprockets/utils/gzip.rb +45 -14
- data/lib/sprockets/version.rb +1 -1
- metadata +32 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 52d1dd6743105d82450959d44e27538e02130e7e
|
4
|
+
data.tar.gz: 02f58032703403898778cc33d6a56e0ca8bbee01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac089336d45577a2647ba6b329c5a62862613674be5969f4312e0d7afbb0cf3a9a06cbc7d9db7dd55649fac74c234da54d4482f83d091c4d2357269502006d99
|
7
|
+
data.tar.gz: 990363e0a8e9545ad6243279075cad733d7b403b45737b0c76b35d4647824e693c9f012c88b4220a431970d649dc7ad3582980311dc30c8e2b7b1871c1e5d611
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,19 @@
|
|
2
2
|
|
3
3
|
Get upgrade notes from Sprockets 3.x to 4.x at https://github.com/rails/sprockets/blob/master/UPGRADING.md
|
4
4
|
|
5
|
+
## Master
|
6
|
+
|
7
|
+
|
8
|
+
## 4.0.0.beta4
|
9
|
+
|
10
|
+
- Changing the version now busts the digest of all assets [#404]
|
11
|
+
- Exporter interface added [#386]
|
12
|
+
- Using ENV vars in templates will recompile templates when the env vars change. [#365]
|
13
|
+
- Source maps for imported sass files with sassc is now fixed [#391]
|
14
|
+
- Load paths now in error messages [#322]
|
15
|
+
- Cache key added to babel processor [#387]
|
16
|
+
- `Environment#find_asset!` can now be used to raise an exception when asset could not be found [#379]
|
17
|
+
|
5
18
|
## 4.0.0.beta3
|
6
19
|
|
7
20
|
- Source Map fixes [#255] [#367]
|
data/bin/sprockets
CHANGED
data/lib/sprockets.rb
CHANGED
@@ -34,8 +34,10 @@ module Sprockets
|
|
34
34
|
registered_transformers: [].freeze,
|
35
35
|
root: __dir__.dup.freeze,
|
36
36
|
transformers: Hash.new { |h, k| {}.freeze }.freeze,
|
37
|
+
exporters: Hash.new { |h, k| Set.new.freeze }.freeze,
|
37
38
|
version: "",
|
38
|
-
gzip_enabled: true
|
39
|
+
gzip_enabled: true,
|
40
|
+
export_concurrent: true
|
39
41
|
}.freeze
|
40
42
|
|
41
43
|
@context_class = Context
|
@@ -126,6 +128,7 @@ module Sprockets
|
|
126
128
|
register_bundle_metadata_reducer '*/*', :data, proc { String.new("") }, :concat
|
127
129
|
register_bundle_metadata_reducer 'application/javascript', :data, proc { String.new("") }, Utils.method(:concat_javascript_sources)
|
128
130
|
register_bundle_metadata_reducer '*/*', :links, :+
|
131
|
+
register_bundle_metadata_reducer '*/*', :sources, proc { [] }, :+
|
129
132
|
register_bundle_metadata_reducer '*/*', :map, SourceMapUtils.method(:concat_source_maps)
|
130
133
|
|
131
134
|
require 'sprockets/closure_compressor'
|
@@ -197,6 +200,11 @@ module Sprockets
|
|
197
200
|
register_mime_type 'application/html+ruby', extensions: ['.html.erb', '.erb', '.rhtml'], charset: :html
|
198
201
|
register_mime_type 'application/xml+ruby', extensions: ['.xml.erb', '.rxml']
|
199
202
|
|
203
|
+
require 'sprockets/exporters/file_exporter'
|
204
|
+
require 'sprockets/exporters/zlib_exporter'
|
205
|
+
require 'sprockets/exporters/zopfli_exporter'
|
206
|
+
register_exporter '*/*', Exporters::FileExporter
|
207
|
+
register_exporter '*/*', Exporters::ZlibExporter
|
200
208
|
|
201
209
|
register_dependency_resolver 'environment-version' do |env|
|
202
210
|
env.version
|
@@ -210,6 +218,10 @@ module Sprockets
|
|
210
218
|
register_dependency_resolver 'processors' do |env, str|
|
211
219
|
env.resolve_processors_cache_key_uri(str)
|
212
220
|
end
|
221
|
+
register_dependency_resolver 'env' do |env, str|
|
222
|
+
_, var = str.split(':', 2)
|
223
|
+
ENV[var]
|
224
|
+
end
|
213
225
|
|
214
226
|
depend_on 'environment-version'
|
215
227
|
depend_on 'environment-paths'
|
data/lib/sprockets/asset.rb
CHANGED
@@ -67,6 +67,13 @@ module Sprockets
|
|
67
67
|
logical_path.sub(/\.(\w+)$/) { |ext| "-#{etag}#{ext}" }
|
68
68
|
end
|
69
69
|
|
70
|
+
# Public: Return load path + logical path with digest spliced in.
|
71
|
+
#
|
72
|
+
# Returns String.
|
73
|
+
def full_digest_path
|
74
|
+
File.join(@load_path, digest_path)
|
75
|
+
end
|
76
|
+
|
70
77
|
# Public: Returns String MIME type of asset. Returns nil if type is unknown.
|
71
78
|
attr_reader :content_type
|
72
79
|
|
data/lib/sprockets/autoload.rb
CHANGED
@@ -6,10 +6,11 @@ module Sprockets
|
|
6
6
|
autoload :CoffeeScript, 'sprockets/autoload/coffee_script'
|
7
7
|
autoload :Eco, 'sprockets/autoload/eco'
|
8
8
|
autoload :EJS, 'sprockets/autoload/ejs'
|
9
|
-
autoload :JSMinC, 'sprockets/autoload/jsminc'
|
9
|
+
autoload :JSMinC, 'sprockets/autoload/jsminc'
|
10
10
|
autoload :Sass, 'sprockets/autoload/sass'
|
11
11
|
autoload :SassC, 'sprockets/autoload/sassc'
|
12
12
|
autoload :Uglifier, 'sprockets/autoload/uglifier'
|
13
13
|
autoload :YUI, 'sprockets/autoload/yui'
|
14
|
+
autoload :Zopfli, 'sprockets/autoload/zopfli'
|
14
15
|
end
|
15
16
|
end
|
@@ -16,6 +16,12 @@ module Sprockets
|
|
16
16
|
instance.call(input)
|
17
17
|
end
|
18
18
|
|
19
|
+
def self.cache_key
|
20
|
+
instance.cache_key
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :cache_key
|
24
|
+
|
19
25
|
def initialize(options = {})
|
20
26
|
@options = options.merge({
|
21
27
|
'blacklist' => (options['blacklist'] || []) + ['useStrict'],
|
data/lib/sprockets/base.rb
CHANGED
@@ -93,6 +93,16 @@ module Sprockets
|
|
93
93
|
find_asset(*args)
|
94
94
|
end
|
95
95
|
|
96
|
+
# Find asset by logical path or expanded path.
|
97
|
+
#
|
98
|
+
# If the asset is not found an error will be raised.
|
99
|
+
def find_asset!(*args)
|
100
|
+
uri, _ = resolve!(*args)
|
101
|
+
if uri
|
102
|
+
load(uri)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
96
106
|
# Pretty inspect
|
97
107
|
def inspect
|
98
108
|
"#<#{self.class}:0x#{object_id.to_s(16)} " +
|
@@ -102,12 +102,33 @@ module Sprockets
|
|
102
102
|
|
103
103
|
# Public: Enable or disable the creation of Gzip files.
|
104
104
|
#
|
105
|
-
#
|
105
|
+
# To disable gzip generation set to a falsey value:
|
106
106
|
#
|
107
107
|
# environment.gzip = false
|
108
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
|
+
#
|
109
116
|
def gzip=(gzip)
|
110
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
|
111
132
|
end
|
112
133
|
end
|
113
134
|
end
|
@@ -4,12 +4,13 @@ require 'sprockets/dependencies'
|
|
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, 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
|
data/lib/sprockets/context.rb
CHANGED
@@ -18,6 +18,24 @@ module Sprockets
|
|
18
18
|
# The `Context` also collects dependencies declared by
|
19
19
|
# assets. See `DirectiveProcessor` for an example of this.
|
20
20
|
class Context
|
21
|
+
# Internal: Proxy for ENV that keeps track of the environment variables used
|
22
|
+
class ENVProxy < SimpleDelegator
|
23
|
+
def initialize(context)
|
24
|
+
@context = context
|
25
|
+
super(ENV)
|
26
|
+
end
|
27
|
+
|
28
|
+
def [](key)
|
29
|
+
@context.depend_on_env(key)
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
def fetch(key, *)
|
34
|
+
@context.depend_on_env(key)
|
35
|
+
super
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
21
39
|
attr_reader :environment, :filename
|
22
40
|
|
23
41
|
def initialize(input)
|
@@ -42,6 +60,10 @@ module Sprockets
|
|
42
60
|
dependencies: @dependencies }
|
43
61
|
end
|
44
62
|
|
63
|
+
def env_proxy
|
64
|
+
ENVProxy.new(self)
|
65
|
+
end
|
66
|
+
|
45
67
|
# Returns the environment path that contains the file.
|
46
68
|
#
|
47
69
|
# If `app/javascripts` and `app/stylesheets` are in your path, and
|
@@ -122,6 +144,15 @@ module Sprockets
|
|
122
144
|
load(resolve(path))
|
123
145
|
end
|
124
146
|
|
147
|
+
# `depend_on_env` allows you to state a dependency on an environment
|
148
|
+
# variable.
|
149
|
+
#
|
150
|
+
# This is used for caching purposes. Any changes in the value of the
|
151
|
+
# environment variable will invalidate the cache of the source file.
|
152
|
+
def depend_on_env(key)
|
153
|
+
@dependencies << "env:#{key}"
|
154
|
+
end
|
155
|
+
|
125
156
|
# `require_asset` declares `path` as a dependency of the file. The
|
126
157
|
# dependency will be inserted before the file and will only be
|
127
158
|
# included once.
|
@@ -45,12 +45,8 @@ module Sprockets
|
|
45
45
|
digest << 'Symbol'.freeze
|
46
46
|
digest << val.to_s
|
47
47
|
},
|
48
|
-
|
49
|
-
digest << '
|
50
|
-
digest << val.to_s
|
51
|
-
},
|
52
|
-
Bignum => ->(val, digest) {
|
53
|
-
digest << 'Bignum'.freeze
|
48
|
+
Integer => ->(val, digest) {
|
49
|
+
digest << 'Integer'.freeze
|
54
50
|
digest << val.to_s
|
55
51
|
},
|
56
52
|
Array => ->(val, digest) {
|
@@ -74,6 +70,16 @@ module Sprockets
|
|
74
70
|
digest << val.name
|
75
71
|
},
|
76
72
|
}
|
73
|
+
if 0.class != Integer # Ruby < 2.4
|
74
|
+
ADD_VALUE_TO_DIGEST[Fixnum] = ->(val, digest) {
|
75
|
+
digest << 'Integer'.freeze
|
76
|
+
digest << val.to_s
|
77
|
+
}
|
78
|
+
ADD_VALUE_TO_DIGEST[Bignum] = ->(val, digest) {
|
79
|
+
digest << 'Integer'.freeze
|
80
|
+
digest << val.to_s
|
81
|
+
}
|
82
|
+
end
|
77
83
|
ADD_VALUE_TO_DIGEST.default_proc = ->(_, val) {
|
78
84
|
raise TypeError, "couldn't digest #{ val }"
|
79
85
|
}
|
@@ -1,31 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require 'erb'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
class Sprockets::ERBProcessor
|
5
|
+
# Public: Return singleton instance with default options.
|
6
|
+
#
|
7
|
+
# Returns ERBProcessor object.
|
8
|
+
def self.instance
|
9
|
+
@instance ||= new
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.call(input)
|
13
|
+
instance.call(input)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(&block)
|
17
|
+
@block = block
|
18
|
+
end
|
12
19
|
|
13
|
-
|
14
|
-
|
15
|
-
|
20
|
+
def call(input)
|
21
|
+
engine = ::ERB.new(input[:data], nil, '<>')
|
22
|
+
engine.filename = input[:filename]
|
16
23
|
|
17
|
-
|
18
|
-
|
19
|
-
|
24
|
+
context = input[:environment].context_class.new(input)
|
25
|
+
klass = (class << context; self; end)
|
26
|
+
klass.const_set(:ENV, context.env_proxy)
|
27
|
+
klass.class_eval(&@block) if @block
|
20
28
|
|
21
|
-
|
22
|
-
|
23
|
-
context = input[:environment].context_class.new(input)
|
24
|
-
klass = (class << context; self; end)
|
25
|
-
klass.class_eval(&@block) if @block
|
26
|
-
engine.def_method(klass, :_evaluate_template, input[:filename])
|
27
|
-
data = context._evaluate_template
|
28
|
-
context.metadata.merge(data: data)
|
29
|
-
end
|
29
|
+
data = engine.result(context.instance_eval('binding'))
|
30
|
+
context.metadata.merge(data: data)
|
30
31
|
end
|
31
32
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Sprockets
|
2
|
+
module Exporters
|
3
|
+
# Convienence class for all exporters to inherit from
|
4
|
+
#
|
5
|
+
# An exporter is responsible for exporting a Sprockets::Asset
|
6
|
+
# to a file system. For example the Exporters::File class
|
7
|
+
# writes the asset to it's destination. The Exporters::Zlib class
|
8
|
+
# writes a gzip copy of the asset to disk.
|
9
|
+
class Base
|
10
|
+
attr_reader :asset, :environment, :directory, :target
|
11
|
+
|
12
|
+
# Public: Creates new instance
|
13
|
+
#
|
14
|
+
# Initialize will be called with
|
15
|
+
# keyword arguments:
|
16
|
+
#
|
17
|
+
# - asset: An instance of Sprockets::Asset.
|
18
|
+
# - environment: An instance of Sprockets::Environment.
|
19
|
+
# - directory: String representing the target directory to write to.
|
20
|
+
#
|
21
|
+
# These will all be stored as accessible values. In addition a
|
22
|
+
# +target+ will be available which is the target directory and
|
23
|
+
# the asset's digest path combined.
|
24
|
+
def initialize(asset: nil, environment: nil, directory: nil)
|
25
|
+
@asset = asset
|
26
|
+
@environment = environment
|
27
|
+
@directory = directory
|
28
|
+
@target = ::File.join(directory, asset.digest_path)
|
29
|
+
setup
|
30
|
+
end
|
31
|
+
|
32
|
+
# Public: Callback that is executed after intialization
|
33
|
+
#
|
34
|
+
# Any setup that needs to be done can be performed in the +setup+
|
35
|
+
# method. It will be called immediately after initialization.
|
36
|
+
def setup
|
37
|
+
end
|
38
|
+
|
39
|
+
# Public: Handles logic for skipping exporter and notifying logger
|
40
|
+
#
|
41
|
+
# The `skip?` will be called before anything will be written.
|
42
|
+
# If `skip?` returns truthy it will not continue. This method
|
43
|
+
# takes a `logger` that responds to +debug+ and +info+. The `skip?`
|
44
|
+
# method is the only place expected to write to a logger, any other
|
45
|
+
# messages may produce jumbled logs.
|
46
|
+
def skip?(logger)
|
47
|
+
false
|
48
|
+
end
|
49
|
+
|
50
|
+
# Public: Contains logic for writing "exporting" asset to disk
|
51
|
+
#
|
52
|
+
# If the exporter is not skipped it then Sprockets will execute it's
|
53
|
+
# `call` method. This method takes no arguments and should only use
|
54
|
+
# elements passed in via initialize or stored in `setup`.
|
55
|
+
def call
|
56
|
+
raise "Must subclass and implement call"
|
57
|
+
end
|
58
|
+
|
59
|
+
# Public: Yields a file that can be written to with the input
|
60
|
+
#
|
61
|
+
# `filename`. Defaults to the `target`. Method
|
62
|
+
# is safe to use in forked or threaded environments.
|
63
|
+
def write(filename = target)
|
64
|
+
FileUtils.mkdir_p File.dirname(filename)
|
65
|
+
PathUtils.atomic_write(filename) do |f|
|
66
|
+
yield f
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'sprockets/exporters/base'
|
2
|
+
|
3
|
+
module Sprockets
|
4
|
+
module Exporters
|
5
|
+
# Writes a an asset file to disk
|
6
|
+
class FileExporter < Exporters::Base
|
7
|
+
def skip?(logger)
|
8
|
+
if ::File.exist?(target)
|
9
|
+
logger.debug "Skipping #{ target }, already exists"
|
10
|
+
true
|
11
|
+
else
|
12
|
+
logger.info "Writing #{ target }"
|
13
|
+
false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
write(target) do |file|
|
19
|
+
file.write(asset.source)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'sprockets/exporters/base'
|
2
|
+
require 'sprockets/utils/gzip'
|
3
|
+
|
4
|
+
module Sprockets
|
5
|
+
module Exporters
|
6
|
+
# Generates a `.gz` file using the zlib algorithm built into
|
7
|
+
# Ruby's standard library.
|
8
|
+
class ZlibExporter < Exporters::Base
|
9
|
+
def setup
|
10
|
+
@gzip_target = "#{ target }.gz"
|
11
|
+
@gzip = Sprockets::Utils::Gzip.new(asset, archiver: Utils::Gzip::ZlibArchiver)
|
12
|
+
end
|
13
|
+
|
14
|
+
def skip?(logger)
|
15
|
+
return true if environment.skip_gzip?
|
16
|
+
return true if @gzip.cannot_compress?
|
17
|
+
if ::File.exist?(@gzip_target)
|
18
|
+
logger.debug "Skipping #{ @gzip_target }, already exists"
|
19
|
+
true
|
20
|
+
else
|
21
|
+
logger.info "Writing #{ @gzip_target }"
|
22
|
+
false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def call
|
27
|
+
write(@gzip_target) do |file|
|
28
|
+
@gzip.compress(file, target)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'sprockets/exporters/zlib_exporter'
|
2
|
+
|
3
|
+
module Sprockets
|
4
|
+
module Exporters
|
5
|
+
# Generates a `.gz` file using the zopfli algorithm from the
|
6
|
+
# Zopfli gem.
|
7
|
+
class ZopfliExporter < ZlibExporter
|
8
|
+
def setup
|
9
|
+
@gzip_target = "#{ target }.gz"
|
10
|
+
@gzip = Sprockets::Utils::Gzip.new(asset, archiver: Utils::Gzip::ZopfliArchiver)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Sprockets
|
2
|
+
# `Exporting` is an internal mixin whose public methods are exposed on
|
3
|
+
# the `Environment` and `CachedEnvironment` classes.
|
4
|
+
module Exporting
|
5
|
+
# Exporters are ran on the assets:precompile task
|
6
|
+
def exporters
|
7
|
+
config[:exporters]
|
8
|
+
end
|
9
|
+
|
10
|
+
# Public: Registers a new Exporter `klass` for `mime_type`.
|
11
|
+
#
|
12
|
+
# If your exporter depends on one or more other exporters you can
|
13
|
+
# specify this via the `depend_on` keyword.
|
14
|
+
#
|
15
|
+
# register_exporter '*/*', Sprockets::Exporters::ZlibExporter
|
16
|
+
#
|
17
|
+
# This ensures that `Sprockets::Exporters::File` will always execute before
|
18
|
+
# `Sprockets::Exporters::Zlib`
|
19
|
+
def register_exporter(mime_types, klass = nil)
|
20
|
+
mime_types = Array(mime_types)
|
21
|
+
|
22
|
+
mime_types.each do |mime_type|
|
23
|
+
self.config = hash_reassoc(config, :exporters, mime_type) do |_exporters|
|
24
|
+
_exporters << klass
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Public: Remove Exporting processor `klass` for `mime_type`.
|
30
|
+
#
|
31
|
+
# environment.unregister_exporter '*/*', Sprockets::Exporters::Zlib
|
32
|
+
#
|
33
|
+
# Can be called without a mime type
|
34
|
+
#
|
35
|
+
# environment.unregister_exporter Sprockets::Exporters::Zlib
|
36
|
+
#
|
37
|
+
# Does not remove any exporters that depend on `klass`.
|
38
|
+
def unregister_exporter(mime_types, exporter = nil)
|
39
|
+
unless mime_types.is_a? Array
|
40
|
+
if mime_types.is_a? String
|
41
|
+
mime_types = [mime_types]
|
42
|
+
else # called with no mime type
|
43
|
+
exporter = mime_types
|
44
|
+
mime_types = nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
self.config = hash_reassoc(config, :exporters) do |_exporters|
|
49
|
+
_exporters.each do |mime_type, exporters_array|
|
50
|
+
next if mime_types && !mime_types.include?(mime_type)
|
51
|
+
if exporters_array.include? exporter
|
52
|
+
_exporters[mime_type] = exporters_array.dup.delete exporter
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Public: Checks if concurrent exporting is allowed
|
59
|
+
def export_concurrent
|
60
|
+
config[:export_concurrent]
|
61
|
+
end
|
62
|
+
|
63
|
+
# Public: Enable or disable the concurrently exporting files
|
64
|
+
#
|
65
|
+
# Defaults to true.
|
66
|
+
#
|
67
|
+
# environment.export_concurrent = false
|
68
|
+
#
|
69
|
+
def export_concurrent=(export_concurrent)
|
70
|
+
self.config = config.merge(export_concurrent: export_concurrent).freeze
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/sprockets/loader.rb
CHANGED
@@ -163,7 +163,7 @@ module Sprockets
|
|
163
163
|
source = result.delete(:data)
|
164
164
|
metadata = result
|
165
165
|
metadata[:charset] = source.encoding.name.downcase unless metadata.key?(:charset)
|
166
|
-
metadata[:digest] = digest(source)
|
166
|
+
metadata[:digest] = digest(self.version + source)
|
167
167
|
metadata[:length] = source.bytesize
|
168
168
|
else
|
169
169
|
dependencies << build_file_digest_uri(unloaded.filename)
|
data/lib/sprockets/manifest.rb
CHANGED
@@ -5,7 +5,6 @@ require 'time'
|
|
5
5
|
require 'concurrent'
|
6
6
|
|
7
7
|
require 'sprockets/manifest_utils'
|
8
|
-
require 'sprockets/utils/gzip'
|
9
8
|
|
10
9
|
module Sprockets
|
11
10
|
# The Manifest logs the contents of assets compiled to a single directory. It
|
@@ -147,7 +146,7 @@ module Sprockets
|
|
147
146
|
end
|
148
147
|
end
|
149
148
|
|
150
|
-
# Compile
|
149
|
+
# Compile asset to directory. The asset is written to a
|
151
150
|
# fingerprinted filename like
|
152
151
|
# `application-2e8e9a7c6b0aafa0c9bdeec90ea30213.js`. An entry is
|
153
152
|
# also inserted into the manifest file.
|
@@ -159,14 +158,15 @@ module Sprockets
|
|
159
158
|
raise Error, "manifest requires environment for compilation"
|
160
159
|
end
|
161
160
|
|
162
|
-
filenames
|
163
|
-
|
164
|
-
|
161
|
+
filenames = []
|
162
|
+
concurrent_exporters = []
|
163
|
+
executor = Concurrent::FixedThreadPool.new(Concurrent.processor_count)
|
165
164
|
|
166
165
|
find(*args) do |asset|
|
166
|
+
mtime = Time.now.iso8601
|
167
167
|
files[asset.digest_path] = {
|
168
168
|
'logical_path' => asset.logical_path,
|
169
|
-
'mtime' =>
|
169
|
+
'mtime' => mtime,
|
170
170
|
'size' => asset.bytesize,
|
171
171
|
'digest' => asset.hexdigest,
|
172
172
|
|
@@ -177,34 +177,28 @@ module Sprockets
|
|
177
177
|
}
|
178
178
|
assets[asset.logical_path] = asset.digest_path
|
179
179
|
|
180
|
-
target = File.join(dir, asset.digest_path)
|
181
|
-
|
182
|
-
if File.exist?(target)
|
183
|
-
logger.debug "Skipping #{target}, already exists"
|
184
|
-
else
|
185
|
-
logger.info "Writing #{target}"
|
186
|
-
write_file = Concurrent::Future.execute { asset.write_to target }
|
187
|
-
concurrent_writers << write_file
|
188
|
-
end
|
189
180
|
filenames << asset.filename
|
190
181
|
|
191
|
-
|
192
|
-
|
193
|
-
|
182
|
+
promise = nil
|
183
|
+
exporters_for_asset(asset) do |exporter|
|
184
|
+
next if exporter.skip?(logger)
|
194
185
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
logger.info "Writing #{target}.gz"
|
199
|
-
concurrent_compressors << Concurrent::Future.execute do
|
200
|
-
write_file.wait! if write_file
|
201
|
-
gzip.compress(target)
|
186
|
+
if !environment.export_concurrent
|
187
|
+
exporter.call
|
188
|
+
next
|
202
189
|
end
|
203
|
-
end
|
204
190
|
|
191
|
+
if promise.nil?
|
192
|
+
promise = Concurrent::Promise.new(executor: executor) { exporter.call }
|
193
|
+
concurrent_exporters << promise.execute
|
194
|
+
else
|
195
|
+
concurrent_exporters << promise.then { exporter.call }
|
196
|
+
end
|
197
|
+
end
|
205
198
|
end
|
206
|
-
|
207
|
-
|
199
|
+
|
200
|
+
# make sure all exporters have finished before returning the main thread
|
201
|
+
concurrent_exporters.each(&:wait!)
|
208
202
|
save
|
209
203
|
|
210
204
|
filenames
|
@@ -284,6 +278,35 @@ module Sprockets
|
|
284
278
|
end
|
285
279
|
|
286
280
|
private
|
281
|
+
|
282
|
+
# Given an asset, finds all exporters that
|
283
|
+
# match its mime-type.
|
284
|
+
#
|
285
|
+
# Will yield each expoter to the passed in block.
|
286
|
+
#
|
287
|
+
# array = []
|
288
|
+
# puts asset.content_type # => "application/javascript"
|
289
|
+
# exporters_for_asset(asset) do |exporter|
|
290
|
+
# array << exporter
|
291
|
+
# end
|
292
|
+
# # puts array => [Exporters::FileExporter, Exporters::ZlibExporter]
|
293
|
+
def exporters_for_asset(asset)
|
294
|
+
exporters = [Exporters::FileExporter]
|
295
|
+
|
296
|
+
environment.exporters.each do |mime_type, exporter_list|
|
297
|
+
next unless environment.match_mime_type? asset.content_type, mime_type
|
298
|
+
exporter_list.each do |exporter|
|
299
|
+
exporters << exporter
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
exporters.uniq!
|
304
|
+
|
305
|
+
exporters.each do |exporter|
|
306
|
+
yield exporter.new(asset: asset, environment: environment, directory: dir)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
287
310
|
def json_decode(obj)
|
288
311
|
JSON.parse(obj, create_additions: false)
|
289
312
|
end
|
data/lib/sprockets/path_utils.rb
CHANGED
@@ -6,6 +6,7 @@ module Sprockets
|
|
6
6
|
# when code actually wants to reference ::FileUtils.
|
7
7
|
module PathUtils
|
8
8
|
extend self
|
9
|
+
require 'pathname'
|
9
10
|
|
10
11
|
# Public: Like `File.stat`.
|
11
12
|
#
|
@@ -73,8 +74,6 @@ module Sprockets
|
|
73
74
|
#
|
74
75
|
# Returns true if path is absolute, otherwise false.
|
75
76
|
if File::ALT_SEPARATOR
|
76
|
-
require 'pathname'
|
77
|
-
|
78
77
|
# On Windows, ALT_SEPARATOR is \
|
79
78
|
# Delegate to Pathname since the logic gets complex.
|
80
79
|
def absolute_path?(path)
|
@@ -102,6 +101,33 @@ module Sprockets
|
|
102
101
|
path =~ /^\.\.?($|#{SEPARATOR_PATTERN})/ ? true : false
|
103
102
|
end
|
104
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
|
+
|
105
131
|
# Internal: Get relative path for root path and subpath.
|
106
132
|
#
|
107
133
|
# path - String path
|
data/lib/sprockets/processing.rb
CHANGED
@@ -218,9 +218,9 @@ module Sprockets
|
|
218
218
|
end
|
219
219
|
end
|
220
220
|
|
221
|
-
def unregister_config_processor(type, mime_type,
|
221
|
+
def unregister_config_processor(type, mime_type, processor)
|
222
222
|
self.config = hash_reassoc(config, type, mime_type) do |processors|
|
223
|
-
processors.
|
223
|
+
processors.delete_if { |p| p == processor || p.class == processor }
|
224
224
|
processors
|
225
225
|
end
|
226
226
|
end
|
@@ -116,12 +116,10 @@ module Sprockets
|
|
116
116
|
VALID_METADATA_VALUE_TYPES = Set.new([
|
117
117
|
String,
|
118
118
|
Symbol,
|
119
|
-
Fixnum,
|
120
|
-
Bignum,
|
121
119
|
TrueClass,
|
122
120
|
FalseClass,
|
123
121
|
NilClass
|
124
|
-
]).freeze
|
122
|
+
] + (0.class == Integer ? [Integer] : [Bignum, Fixnum])).freeze
|
125
123
|
|
126
124
|
# Internal: Set of all nested compound metadata types that can nest values.
|
127
125
|
VALID_METADATA_COMPOUND_TYPES = Set.new([
|
data/lib/sprockets/resolve.rb
CHANGED
@@ -100,11 +100,14 @@ module Sprockets
|
|
100
100
|
|
101
101
|
private
|
102
102
|
|
103
|
+
def expand_source(source, env)
|
104
|
+
uri, _ = env.resolve!(source, pipeline: :source)
|
105
|
+
env.load(uri).digest_path
|
106
|
+
end
|
107
|
+
|
103
108
|
def expand_map_sources(mapping, env)
|
104
109
|
mapping.each do |map|
|
105
|
-
|
106
|
-
source_path = env.load(uri).digest_path
|
107
|
-
map[:source] = source_path
|
110
|
+
map[:source] = expand_source(map[:source], env)
|
108
111
|
end
|
109
112
|
end
|
110
113
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require 'sprockets/sass_processor'
|
3
|
+
require 'sprockets/path_utils'
|
3
4
|
require 'base64'
|
4
5
|
|
5
6
|
module Sprockets
|
@@ -22,39 +23,42 @@ module Sprockets
|
|
22
23
|
options = engine_options(input, context)
|
23
24
|
engine = Autoload::SassC::Engine.new(input[:data], options)
|
24
25
|
|
25
|
-
|
26
|
-
engine.render
|
26
|
+
css = Utils.module_include(Autoload::SassC::Script::Functions, @functions) do
|
27
|
+
engine.render.sub(/^\n^\/\*# sourceMappingURL=.*\*\/$/m, '')
|
27
28
|
end
|
28
29
|
|
29
|
-
|
30
|
-
|
30
|
+
map = SourceMapUtils.decode_json_source_map(engine.source_map)
|
31
|
+
sources = map['sources'].map do |s|
|
32
|
+
expand_source(PathUtils.join(File.dirname(input[:filename]), s), input[:environment])
|
33
|
+
end
|
34
|
+
|
35
|
+
map = map["mappings"].each do |m|
|
36
|
+
m[:source] = PathUtils.join(File.dirname(input[:filename]), m[:source])
|
37
|
+
end
|
31
38
|
|
32
39
|
map = SourceMapUtils.combine_source_maps(
|
33
40
|
input[:metadata][:map],
|
34
|
-
|
41
|
+
expand_map_sources(map, input[:environment])
|
35
42
|
)
|
36
43
|
|
37
44
|
engine.dependencies.each do |dependency|
|
38
45
|
context.metadata[:dependencies] << URIUtils.build_file_digest_uri(dependency.filename)
|
39
46
|
end
|
40
47
|
|
41
|
-
context.metadata.merge(data: css, map: map)
|
48
|
+
context.metadata.merge(data: css, map: map, sources: sources)
|
42
49
|
end
|
43
50
|
|
44
51
|
private
|
45
52
|
|
46
|
-
def change_source(mappings, source)
|
47
|
-
mappings.each { |m| m[:source] = source }
|
48
|
-
end
|
49
|
-
|
50
53
|
def engine_options(input, context)
|
51
54
|
merge_options({
|
52
55
|
filename: input[:filename],
|
53
56
|
syntax: self.class.syntax,
|
54
57
|
load_paths: input[:environment].paths,
|
55
58
|
importer: @importer_class,
|
56
|
-
|
57
|
-
source_map_file:
|
59
|
+
source_map_contents: true,
|
60
|
+
source_map_file: "#{input[:filename]}.map",
|
61
|
+
omit_source_map_url: true,
|
58
62
|
sprockets: {
|
59
63
|
context: context,
|
60
64
|
environment: input[:environment],
|
@@ -21,8 +21,10 @@ module Sprockets
|
|
21
21
|
uri, _ = env.resolve!(input[:filename], accept: map_type)
|
22
22
|
map = env.load(uri)
|
23
23
|
|
24
|
+
path = PathUtils.relative_path_from(input[:filename], map.full_digest_path)
|
25
|
+
|
24
26
|
asset.metadata.merge(
|
25
|
-
data: asset.source + (comment %
|
27
|
+
data: asset.source + (comment % path),
|
26
28
|
links: asset.links + [asset.uri, map.uri]
|
27
29
|
)
|
28
30
|
end
|
@@ -17,9 +17,10 @@ module Sprockets
|
|
17
17
|
|
18
18
|
env = input[:environment]
|
19
19
|
|
20
|
-
uri, _
|
21
|
-
asset
|
22
|
-
map
|
20
|
+
uri, _ = env.resolve!(input[:filename], accept: accept)
|
21
|
+
asset = env.load(uri)
|
22
|
+
map = asset.metadata[:map] || []
|
23
|
+
sources = asset.metadata[:sources]
|
23
24
|
|
24
25
|
# TODO: Because of the default piplene hack we have to apply dependencies
|
25
26
|
# from compiled asset to the source map, otherwise the source map cache
|
@@ -39,7 +40,7 @@ module Sprockets
|
|
39
40
|
links << uri
|
40
41
|
end
|
41
42
|
|
42
|
-
json = env.encode_json_source_map(map, filename: asset.logical_path)
|
43
|
+
json = env.encode_json_source_map(map, sources: sources, filename: asset.logical_path)
|
43
44
|
|
44
45
|
{ data: json, links: links, dependencies: dependencies }
|
45
46
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require 'json'
|
3
|
+
require 'sprockets/path_utils'
|
3
4
|
|
4
5
|
module Sprockets
|
5
6
|
module SourceMapUtils
|
@@ -136,7 +137,11 @@ module Sprockets
|
|
136
137
|
case mappings
|
137
138
|
when String
|
138
139
|
when Array
|
139
|
-
|
140
|
+
mappings.each do |m|
|
141
|
+
m[:source] = PathUtils.relative_path_from(filename, m[:source])
|
142
|
+
end if filename
|
143
|
+
sources = sources.map { |s| PathUtils.relative_path_from(filename, s) } if filename && sources
|
144
|
+
sources = (Array(sources) + mappings.map { |m| m[:source] }).uniq.compact
|
140
145
|
names ||= mappings.map { |m| m[:name] }.uniq.compact
|
141
146
|
mappings = encode_vlq_mappings(mappings, sources: sources, names: names)
|
142
147
|
else
|
data/lib/sprockets/utils/gzip.rb
CHANGED
@@ -2,11 +2,49 @@
|
|
2
2
|
module Sprockets
|
3
3
|
module Utils
|
4
4
|
class Gzip
|
5
|
+
# Private: Generates a gzipped file based off of reference asset.
|
6
|
+
#
|
7
|
+
# ZlibArchiver.call(file, source, mtime)
|
8
|
+
#
|
9
|
+
# Compresses a given `source` using stdlib Zlib algorithm
|
10
|
+
# writes contents to the `file` passed in. Sets `mtime` of
|
11
|
+
# written file to passed in `mtime`
|
12
|
+
module ZlibArchiver
|
13
|
+
def self.call(file, source, mtime)
|
14
|
+
gz = Zlib::GzipWriter.new(file, Zlib::BEST_COMPRESSION)
|
15
|
+
gz.mtime = mtime
|
16
|
+
gz.write(source)
|
17
|
+
gz.close
|
18
|
+
|
19
|
+
File.utime(mtime, mtime, file.path)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Private: Generates a gzipped file based off of reference asset.
|
24
|
+
#
|
25
|
+
# ZopfliArchiver.call(file, source, mtime)
|
26
|
+
#
|
27
|
+
# Compresses a given `source` using the zopfli gem
|
28
|
+
# writes contents to the `file` passed in. Sets `mtime` of
|
29
|
+
# written file to passed in `mtime`
|
30
|
+
module ZopfliArchiver
|
31
|
+
def self.call(file, source, mtime)
|
32
|
+
compressed_source = Autoload::Zopfli.deflate(source, format: :gzip, mtime: mtime)
|
33
|
+
file.write(compressed_source)
|
34
|
+
file.close
|
35
|
+
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_reader :content_type, :source, :charset, :archiver
|
41
|
+
|
5
42
|
# Private: Generates a gzipped file based off of reference file.
|
6
|
-
def initialize(asset)
|
43
|
+
def initialize(asset, archiver: ZlibArchiver)
|
7
44
|
@content_type = asset.content_type
|
8
45
|
@source = asset.source
|
9
46
|
@charset = asset.charset
|
47
|
+
@archiver = archiver
|
10
48
|
end
|
11
49
|
|
12
50
|
# What non-text mime types should we compress? This list comes from:
|
@@ -27,7 +65,7 @@ module Sprockets
|
|
27
65
|
# through a compression algorithm would make them larger.
|
28
66
|
#
|
29
67
|
# Return Boolean.
|
30
|
-
def can_compress?
|
68
|
+
def can_compress?
|
31
69
|
# The "charset" of a mime type is present if the value is
|
32
70
|
# encoded text. We can check this value to see if the asset
|
33
71
|
# can be compressed.
|
@@ -39,8 +77,8 @@ module Sprockets
|
|
39
77
|
# Private: Opposite of `can_compress?`.
|
40
78
|
#
|
41
79
|
# Returns Boolean.
|
42
|
-
def cannot_compress?
|
43
|
-
!can_compress?
|
80
|
+
def cannot_compress?
|
81
|
+
!can_compress?
|
44
82
|
end
|
45
83
|
|
46
84
|
# Private: Generates a gzipped file based off of reference asset.
|
@@ -50,16 +88,9 @@ module Sprockets
|
|
50
88
|
# Does not modify the target asset.
|
51
89
|
#
|
52
90
|
# Returns nothing.
|
53
|
-
def compress(target)
|
54
|
-
mtime = PathUtils.stat(target).mtime
|
55
|
-
|
56
|
-
gz = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION)
|
57
|
-
gz.mtime = mtime
|
58
|
-
gz.write(@source)
|
59
|
-
gz.close
|
60
|
-
|
61
|
-
File.utime(mtime, mtime, f.path)
|
62
|
-
end
|
91
|
+
def compress(file, target)
|
92
|
+
mtime = Sprockets::PathUtils.stat(target).mtime
|
93
|
+
archiver.call(file, source, mtime)
|
63
94
|
|
64
95
|
nil
|
65
96
|
end
|
data/lib/sprockets/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sprockets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.0.
|
4
|
+
version: 4.0.0.beta4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Stephenson
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-10-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -231,16 +231,22 @@ dependencies:
|
|
231
231
|
name: sassc
|
232
232
|
requirement: !ruby/object:Gem::Requirement
|
233
233
|
requirements:
|
234
|
-
- - "
|
234
|
+
- - ">="
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: 1.10.1
|
237
|
+
- - "<"
|
235
238
|
- !ruby/object:Gem::Version
|
236
|
-
version: '
|
239
|
+
version: '2.0'
|
237
240
|
type: :development
|
238
241
|
prerelease: false
|
239
242
|
version_requirements: !ruby/object:Gem::Requirement
|
240
243
|
requirements:
|
241
|
-
- - "
|
244
|
+
- - ">="
|
242
245
|
- !ruby/object:Gem::Version
|
243
|
-
version:
|
246
|
+
version: 1.10.1
|
247
|
+
- - "<"
|
248
|
+
- !ruby/object:Gem::Version
|
249
|
+
version: '2.0'
|
244
250
|
- !ruby/object:Gem::Dependency
|
245
251
|
name: uglifier
|
246
252
|
requirement: !ruby/object:Gem::Requirement
|
@@ -269,6 +275,20 @@ dependencies:
|
|
269
275
|
- - "~>"
|
270
276
|
- !ruby/object:Gem::Version
|
271
277
|
version: '0.12'
|
278
|
+
- !ruby/object:Gem::Dependency
|
279
|
+
name: zopfli
|
280
|
+
requirement: !ruby/object:Gem::Requirement
|
281
|
+
requirements:
|
282
|
+
- - "~>"
|
283
|
+
- !ruby/object:Gem::Version
|
284
|
+
version: 0.0.4
|
285
|
+
type: :development
|
286
|
+
prerelease: false
|
287
|
+
version_requirements: !ruby/object:Gem::Requirement
|
288
|
+
requirements:
|
289
|
+
- - "~>"
|
290
|
+
- !ruby/object:Gem::Version
|
291
|
+
version: 0.0.4
|
272
292
|
description: Sprockets is a Rack-based asset packaging system that concatenates and
|
273
293
|
serves JavaScript, CoffeeScript, CSS, Sass, and SCSS.
|
274
294
|
email:
|
@@ -296,6 +316,7 @@ files:
|
|
296
316
|
- lib/sprockets/autoload/sassc.rb
|
297
317
|
- lib/sprockets/autoload/uglifier.rb
|
298
318
|
- lib/sprockets/autoload/yui.rb
|
319
|
+
- lib/sprockets/autoload/zopfli.rb
|
299
320
|
- lib/sprockets/babel_processor.rb
|
300
321
|
- lib/sprockets/base.rb
|
301
322
|
- lib/sprockets/bower.rb
|
@@ -319,6 +340,11 @@ files:
|
|
319
340
|
- lib/sprockets/environment.rb
|
320
341
|
- lib/sprockets/erb_processor.rb
|
321
342
|
- lib/sprockets/errors.rb
|
343
|
+
- lib/sprockets/exporters/base.rb
|
344
|
+
- lib/sprockets/exporters/file_exporter.rb
|
345
|
+
- lib/sprockets/exporters/zlib_exporter.rb
|
346
|
+
- lib/sprockets/exporters/zopfli_exporter.rb
|
347
|
+
- lib/sprockets/exporting.rb
|
322
348
|
- lib/sprockets/file_reader.rb
|
323
349
|
- lib/sprockets/http_utils.rb
|
324
350
|
- lib/sprockets/jsminc_compressor.rb
|