sprockets 3.7.2 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -270
- data/README.md +443 -320
- data/bin/sprockets +11 -7
- data/lib/rake/sprocketstask.rb +3 -2
- data/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
- data/lib/sprockets/asset.rb +16 -21
- data/lib/sprockets/autoload/babel.rb +8 -0
- data/lib/sprockets/autoload/closure.rb +1 -0
- data/lib/sprockets/autoload/coffee_script.rb +1 -0
- data/lib/sprockets/autoload/eco.rb +1 -0
- data/lib/sprockets/autoload/ejs.rb +1 -0
- data/lib/sprockets/autoload/jsminc.rb +8 -0
- data/lib/sprockets/autoload/sass.rb +1 -0
- data/lib/sprockets/autoload/sassc.rb +8 -0
- data/lib/sprockets/autoload/uglifier.rb +1 -0
- data/lib/sprockets/autoload/yui.rb +1 -0
- data/lib/sprockets/autoload/zopfli.rb +7 -0
- data/lib/sprockets/autoload.rb +5 -0
- data/lib/sprockets/babel_processor.rb +66 -0
- data/lib/sprockets/base.rb +47 -10
- data/lib/sprockets/bower.rb +5 -2
- data/lib/sprockets/bundle.rb +40 -4
- data/lib/sprockets/cache/file_store.rb +25 -3
- data/lib/sprockets/cache/memory_store.rb +9 -0
- data/lib/sprockets/cache/null_store.rb +8 -0
- data/lib/sprockets/cache.rb +36 -1
- data/lib/sprockets/cached_environment.rb +14 -19
- data/lib/sprockets/closure_compressor.rb +1 -0
- data/lib/sprockets/coffee_script_processor.rb +18 -4
- data/lib/sprockets/compressing.rb +43 -3
- data/lib/sprockets/configuration.rb +3 -7
- data/lib/sprockets/context.rb +97 -24
- data/lib/sprockets/dependencies.rb +1 -0
- data/lib/sprockets/digest_utils.rb +25 -5
- data/lib/sprockets/directive_processor.rb +45 -35
- data/lib/sprockets/eco_processor.rb +1 -0
- data/lib/sprockets/ejs_processor.rb +1 -0
- data/lib/sprockets/encoding_utils.rb +1 -0
- data/lib/sprockets/environment.rb +9 -4
- data/lib/sprockets/erb_processor.rb +28 -21
- data/lib/sprockets/errors.rb +1 -0
- 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/file_reader.rb +1 -0
- data/lib/sprockets/http_utils.rb +25 -7
- data/lib/sprockets/jsminc_compressor.rb +32 -0
- data/lib/sprockets/jst_processor.rb +11 -10
- data/lib/sprockets/loader.rb +85 -67
- data/lib/sprockets/manifest.rb +64 -62
- data/lib/sprockets/manifest_utils.rb +9 -6
- data/lib/sprockets/mime.rb +8 -42
- data/lib/sprockets/npm.rb +52 -0
- data/lib/sprockets/path_dependency_utils.rb +3 -11
- data/lib/sprockets/path_digest_utils.rb +2 -1
- data/lib/sprockets/path_utils.rb +87 -7
- data/lib/sprockets/paths.rb +1 -0
- data/lib/sprockets/preprocessors/default_source_map.rb +49 -0
- data/lib/sprockets/processing.rb +31 -61
- data/lib/sprockets/processor_utils.rb +24 -35
- data/lib/sprockets/resolve.rb +177 -93
- data/lib/sprockets/sass_cache_store.rb +2 -6
- data/lib/sprockets/sass_compressor.rb +13 -1
- data/lib/sprockets/sass_functions.rb +1 -0
- data/lib/sprockets/sass_importer.rb +1 -0
- data/lib/sprockets/sass_processor.rb +30 -9
- data/lib/sprockets/sassc_compressor.rb +56 -0
- data/lib/sprockets/sassc_processor.rb +297 -0
- data/lib/sprockets/server.rb +26 -23
- data/lib/sprockets/source_map_processor.rb +66 -0
- data/lib/sprockets/source_map_utils.rb +483 -0
- data/lib/sprockets/transformers.rb +63 -35
- data/lib/sprockets/uglifier_compressor.rb +21 -11
- data/lib/sprockets/unloaded_asset.rb +13 -11
- data/lib/sprockets/uri_tar.rb +1 -0
- data/lib/sprockets/uri_utils.rb +11 -8
- data/lib/sprockets/utils/gzip.rb +46 -14
- data/lib/sprockets/utils.rb +41 -74
- data/lib/sprockets/version.rb +2 -1
- data/lib/sprockets/yui_compressor.rb +1 -0
- data/lib/sprockets.rb +99 -39
- metadata +127 -23
- data/LICENSE +0 -21
- data/lib/sprockets/coffee_script_template.rb +0 -17
- data/lib/sprockets/deprecation.rb +0 -90
- data/lib/sprockets/eco_template.rb +0 -17
- data/lib/sprockets/ejs_template.rb +0 -17
- data/lib/sprockets/engines.rb +0 -92
- data/lib/sprockets/erb_template.rb +0 -11
- data/lib/sprockets/legacy.rb +0 -330
- data/lib/sprockets/legacy_proc_processor.rb +0 -35
- data/lib/sprockets/legacy_tilt_processor.rb +0 -29
- data/lib/sprockets/sass_template.rb +0 -19
|
@@ -1,21 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Sprockets
|
|
2
|
-
# Public:
|
|
3
|
+
# Public: JST transformer.
|
|
3
4
|
#
|
|
4
5
|
# Exports server side compiled templates to an object.
|
|
5
6
|
#
|
|
6
|
-
# Name your template "users/show.
|
|
7
|
+
# Name your template "users/show.ejs", "users/new.eco", etc.
|
|
7
8
|
#
|
|
8
9
|
# To accept the default options
|
|
9
10
|
#
|
|
10
|
-
# environment.
|
|
11
|
-
#
|
|
12
|
-
#
|
|
11
|
+
# environment.register_transformer
|
|
12
|
+
# 'application/javascript+function',
|
|
13
|
+
# 'application/javascript', JstProcessor
|
|
13
14
|
#
|
|
14
15
|
# Change the default namespace.
|
|
15
16
|
#
|
|
16
|
-
# environment.
|
|
17
|
-
#
|
|
18
|
-
#
|
|
17
|
+
# environment.register_transformer
|
|
18
|
+
# 'application/javascript+function',
|
|
19
|
+
# 'application/javascript', JstProcessor.new(namespace: 'App.templates')
|
|
19
20
|
#
|
|
20
21
|
class JstProcessor
|
|
21
22
|
def self.default_namespace
|
|
@@ -33,8 +34,8 @@ module Sprockets
|
|
|
33
34
|
instance.call(input)
|
|
34
35
|
end
|
|
35
36
|
|
|
36
|
-
def initialize(
|
|
37
|
-
@namespace =
|
|
37
|
+
def initialize(namespace: self.class.default_namespace)
|
|
38
|
+
@namespace = namespace
|
|
38
39
|
end
|
|
39
40
|
|
|
40
41
|
def call(input)
|
data/lib/sprockets/loader.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'sprockets/asset'
|
|
2
3
|
require 'sprockets/digest_utils'
|
|
3
|
-
require 'sprockets/engines'
|
|
4
4
|
require 'sprockets/errors'
|
|
5
5
|
require 'sprockets/file_reader'
|
|
6
6
|
require 'sprockets/mime'
|
|
@@ -18,7 +18,7 @@ module Sprockets
|
|
|
18
18
|
# object.
|
|
19
19
|
module Loader
|
|
20
20
|
include DigestUtils, PathUtils, ProcessorUtils, URIUtils
|
|
21
|
-
include
|
|
21
|
+
include Mime, Processing, Resolve, Transformers
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
# Public: Load Asset by Asset URI.
|
|
@@ -27,7 +27,6 @@ module Sprockets
|
|
|
27
27
|
# and full path such as:
|
|
28
28
|
# "file:///Path/app/assets/js/app.js?type=application/javascript"
|
|
29
29
|
#
|
|
30
|
-
#
|
|
31
30
|
# Returns Asset.
|
|
32
31
|
def load(uri)
|
|
33
32
|
unloaded = UnloadedAsset.new(uri, self)
|
|
@@ -46,7 +45,7 @@ module Sprockets
|
|
|
46
45
|
# The presence of `paths` indicates dependencies were stored.
|
|
47
46
|
# We can check to see if the dependencies have not changed by "resolving" them and
|
|
48
47
|
# generating a digest key from the resolved entries. If this digest key has not
|
|
49
|
-
# changed the asset will be pulled from cache.
|
|
48
|
+
# changed, the asset will be pulled from cache.
|
|
50
49
|
#
|
|
51
50
|
# If this `paths` is present but the cache returns nothing then `fetch_asset_from_dependency_cache`
|
|
52
51
|
# will confusingly be called again with `paths` set to nil where the asset will be
|
|
@@ -61,10 +60,47 @@ module Sprockets
|
|
|
61
60
|
end
|
|
62
61
|
end
|
|
63
62
|
end
|
|
64
|
-
Asset.new(
|
|
63
|
+
Asset.new(asset)
|
|
65
64
|
end
|
|
66
65
|
|
|
67
66
|
private
|
|
67
|
+
def compress_key_from_hash(hash, key)
|
|
68
|
+
return unless hash.key?(key)
|
|
69
|
+
value = hash[key].dup
|
|
70
|
+
return if !value
|
|
71
|
+
|
|
72
|
+
if block_given?
|
|
73
|
+
value.map! do |x|
|
|
74
|
+
if yield x
|
|
75
|
+
compress_from_root(x)
|
|
76
|
+
else
|
|
77
|
+
x
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
else
|
|
81
|
+
value.map! { |x| compress_from_root(x) }
|
|
82
|
+
end
|
|
83
|
+
hash[key] = value
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def expand_key_from_hash(hash, key)
|
|
88
|
+
return unless hash.key?(key)
|
|
89
|
+
value = hash[key].dup
|
|
90
|
+
return if !value
|
|
91
|
+
if block_given?
|
|
92
|
+
value.map! do |x|
|
|
93
|
+
if yield x
|
|
94
|
+
expand_from_root(x)
|
|
95
|
+
else
|
|
96
|
+
x
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
else
|
|
100
|
+
value.map! { |x| expand_from_root(x) }
|
|
101
|
+
end
|
|
102
|
+
hash[key] = value
|
|
103
|
+
end
|
|
68
104
|
|
|
69
105
|
# Internal: Load asset hash from cache
|
|
70
106
|
#
|
|
@@ -78,15 +114,17 @@ module Sprockets
|
|
|
78
114
|
asset[:uri] = expand_from_root(asset[:uri])
|
|
79
115
|
asset[:load_path] = expand_from_root(asset[:load_path])
|
|
80
116
|
asset[:filename] = expand_from_root(asset[:filename])
|
|
81
|
-
asset[:metadata]
|
|
82
|
-
asset[:metadata]
|
|
83
|
-
asset[:metadata]
|
|
84
|
-
asset[:metadata]
|
|
85
|
-
asset[:metadata]
|
|
117
|
+
expand_key_from_hash(asset[:metadata], :included)
|
|
118
|
+
expand_key_from_hash(asset[:metadata], :links)
|
|
119
|
+
expand_key_from_hash(asset[:metadata], :stubbed)
|
|
120
|
+
expand_key_from_hash(asset[:metadata], :required)
|
|
121
|
+
expand_key_from_hash(asset[:metadata], :to_load)
|
|
122
|
+
expand_key_from_hash(asset[:metadata], :to_link)
|
|
123
|
+
expand_key_from_hash(asset[:metadata], :dependencies) { |uri| uri.start_with?("file-digest://") }
|
|
86
124
|
|
|
87
125
|
asset[:metadata].each_key do |k|
|
|
88
|
-
next unless k
|
|
89
|
-
asset[:metadata]
|
|
126
|
+
next unless k.match?(/_dependencies\z/) # rubocop:disable Performance/EndWith
|
|
127
|
+
expand_key_from_hash(asset[:metadata], k)
|
|
90
128
|
end
|
|
91
129
|
end
|
|
92
130
|
asset
|
|
@@ -103,13 +141,23 @@ module Sprockets
|
|
|
103
141
|
raise FileNotFound, "could not find file: #{unloaded.filename}"
|
|
104
142
|
end
|
|
105
143
|
|
|
106
|
-
|
|
144
|
+
path_to_split =
|
|
145
|
+
if index_alias = unloaded.params[:index_alias]
|
|
146
|
+
expand_from_root index_alias
|
|
147
|
+
else
|
|
148
|
+
unloaded.filename
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
load_path, logical_path = paths_split(config[:paths], path_to_split)
|
|
107
152
|
|
|
108
153
|
unless load_path
|
|
109
|
-
|
|
154
|
+
target = path_to_split
|
|
155
|
+
target += " (index alias of #{unloaded.filename})" if unloaded.params[:index_alias]
|
|
156
|
+
raise FileOutsidePaths, "#{target} is no longer under a load path: #{self.paths.join(', ')}"
|
|
110
157
|
end
|
|
111
158
|
|
|
112
|
-
|
|
159
|
+
extname, file_type = match_path_extname(logical_path, mime_exts)
|
|
160
|
+
logical_path = logical_path.chomp(extname)
|
|
113
161
|
name = logical_path
|
|
114
162
|
|
|
115
163
|
if pipeline = unloaded.params[:pipeline]
|
|
@@ -124,9 +172,9 @@ module Sprockets
|
|
|
124
172
|
raise ConversionError, "could not convert #{file_type.inspect} to #{type.inspect}"
|
|
125
173
|
end
|
|
126
174
|
|
|
127
|
-
processors = processors_for(type, file_type,
|
|
175
|
+
processors = processors_for(type, file_type, pipeline)
|
|
128
176
|
|
|
129
|
-
processors_dep_uri = build_processors_uri(type, file_type,
|
|
177
|
+
processors_dep_uri = build_processors_uri(type, file_type, pipeline)
|
|
130
178
|
dependencies = config[:dependencies] + [processors_dep_uri]
|
|
131
179
|
|
|
132
180
|
# Read into memory and process if theres a processor pipeline
|
|
@@ -139,13 +187,15 @@ module Sprockets
|
|
|
139
187
|
load_path: load_path,
|
|
140
188
|
name: name,
|
|
141
189
|
content_type: type,
|
|
142
|
-
metadata: {
|
|
190
|
+
metadata: {
|
|
191
|
+
dependencies: dependencies
|
|
192
|
+
}
|
|
143
193
|
})
|
|
144
194
|
validate_processor_result!(result)
|
|
145
195
|
source = result.delete(:data)
|
|
146
196
|
metadata = result
|
|
147
197
|
metadata[:charset] = source.encoding.name.downcase unless metadata.key?(:charset)
|
|
148
|
-
metadata[:digest] = digest(source)
|
|
198
|
+
metadata[:digest] = digest(self.version + source)
|
|
149
199
|
metadata[:length] = source.bytesize
|
|
150
200
|
else
|
|
151
201
|
dependencies << build_file_digest_uri(unloaded.filename)
|
|
@@ -168,20 +218,9 @@ module Sprockets
|
|
|
168
218
|
dependencies_digest: DigestUtils.digest(resolve_dependencies(metadata[:dependencies]))
|
|
169
219
|
}
|
|
170
220
|
|
|
171
|
-
asset[:id] =
|
|
221
|
+
asset[:id] = hexdigest(asset)
|
|
172
222
|
asset[:uri] = build_asset_uri(unloaded.filename, unloaded.params.merge(id: asset[:id]))
|
|
173
223
|
|
|
174
|
-
# Deprecated: Avoid tracking Asset mtime
|
|
175
|
-
asset[:mtime] = metadata[:dependencies].map { |u|
|
|
176
|
-
if u.start_with?("file-digest:")
|
|
177
|
-
s = self.stat(parse_file_digest_uri(u))
|
|
178
|
-
s ? s.mtime.to_i : nil
|
|
179
|
-
else
|
|
180
|
-
nil
|
|
181
|
-
end
|
|
182
|
-
}.compact.max
|
|
183
|
-
asset[:mtime] ||= self.stat(unloaded.filename).mtime.to_i
|
|
184
|
-
|
|
185
224
|
store_asset(asset, unloaded)
|
|
186
225
|
asset
|
|
187
226
|
end
|
|
@@ -203,38 +242,17 @@ module Sprockets
|
|
|
203
242
|
if cached_asset[:metadata]
|
|
204
243
|
# Deep dup to avoid modifying `asset`
|
|
205
244
|
cached_asset[:metadata] = cached_asset[:metadata].dup
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
cached_asset[:metadata][:links].map! { |uri| compress_from_root(uri) }
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
if cached_asset[:metadata][:stubbed] && !cached_asset[:metadata][:stubbed].empty?
|
|
217
|
-
cached_asset[:metadata][:stubbed] = cached_asset[:metadata][:stubbed].dup
|
|
218
|
-
cached_asset[:metadata][:stubbed].map! { |uri| compress_from_root(uri) }
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
if cached_asset[:metadata][:required] && !cached_asset[:metadata][:required].empty?
|
|
222
|
-
cached_asset[:metadata][:required] = cached_asset[:metadata][:required].dup
|
|
223
|
-
cached_asset[:metadata][:required].map! { |uri| compress_from_root(uri) }
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
if cached_asset[:metadata][:dependencies] && !cached_asset[:metadata][:dependencies].empty?
|
|
227
|
-
cached_asset[:metadata][:dependencies] = cached_asset[:metadata][:dependencies].dup
|
|
228
|
-
cached_asset[:metadata][:dependencies].map! do |uri|
|
|
229
|
-
uri.start_with?("file-digest://".freeze) ? compress_from_root(uri) : uri
|
|
230
|
-
end
|
|
231
|
-
end
|
|
245
|
+
compress_key_from_hash(cached_asset[:metadata], :included)
|
|
246
|
+
compress_key_from_hash(cached_asset[:metadata], :links)
|
|
247
|
+
compress_key_from_hash(cached_asset[:metadata], :stubbed)
|
|
248
|
+
compress_key_from_hash(cached_asset[:metadata], :required)
|
|
249
|
+
compress_key_from_hash(cached_asset[:metadata], :to_load)
|
|
250
|
+
compress_key_from_hash(cached_asset[:metadata], :to_link)
|
|
251
|
+
compress_key_from_hash(cached_asset[:metadata], :dependencies) { |uri| uri.start_with?("file-digest://") }
|
|
232
252
|
|
|
233
|
-
# compress all _dependencies in metadata like `sass_dependencies`
|
|
234
253
|
cached_asset[:metadata].each do |key, value|
|
|
235
|
-
next unless key
|
|
236
|
-
cached_asset[:metadata]
|
|
237
|
-
cached_asset[:metadata][key].map! {|uri| compress_from_root(uri) }
|
|
254
|
+
next unless key.match?(/_dependencies\z/) # rubocop:disable Performance/EndWith
|
|
255
|
+
compress_key_from_hash(cached_asset[:metadata], key)
|
|
238
256
|
end
|
|
239
257
|
end
|
|
240
258
|
|
|
@@ -255,11 +273,11 @@ module Sprockets
|
|
|
255
273
|
# "processors:type=text/css&file_type=text/css&pipeline=self",
|
|
256
274
|
# "file-digest:///Full/path/app/assets/stylesheets"]
|
|
257
275
|
#
|
|
258
|
-
# Returns back array of things that the given uri
|
|
276
|
+
# Returns back array of things that the given uri depends on
|
|
259
277
|
# For example the environment version, if you're using a different version of sprockets
|
|
260
278
|
# then the dependencies should be different, this is used only for generating cache key
|
|
261
279
|
# for example the "environment-version" may be resolved to "environment-1.0-3.2.0" for
|
|
262
|
-
#
|
|
280
|
+
# version "3.2.0" of sprockets.
|
|
263
281
|
#
|
|
264
282
|
# Any paths that are returned are converted to relative paths
|
|
265
283
|
#
|
|
@@ -276,9 +294,9 @@ module Sprockets
|
|
|
276
294
|
#
|
|
277
295
|
# This method attempts to retrieve the last `limit` number of histories of an asset
|
|
278
296
|
# from the cache a "history" which is an array of unresolved "dependencies" that the asset needs
|
|
279
|
-
# to compile. In this case
|
|
280
|
-
# may rely on jquery.js (so jquery.js is a
|
|
281
|
-
# compilation, such as the VERSION of
|
|
297
|
+
# to compile. In this case a dependency can refer to either an asset e.g. index.js
|
|
298
|
+
# may rely on jquery.js (so jquery.js is a dependency), or other factors that may affect
|
|
299
|
+
# compilation, such as the VERSION of Sprockets (i.e. the environment) and what "processors"
|
|
282
300
|
# are used.
|
|
283
301
|
#
|
|
284
302
|
# For example a history array may look something like this
|
|
@@ -289,7 +307,7 @@ module Sprockets
|
|
|
289
307
|
# "file-digest:///Full/path/app/assets/stylesheets"]]
|
|
290
308
|
#
|
|
291
309
|
# Where the first entry is a Set of dependencies for last generated version of that asset.
|
|
292
|
-
# Multiple versions are stored since
|
|
310
|
+
# Multiple versions are stored since Sprockets keeps the last `limit` number of assets
|
|
293
311
|
# generated present in the system.
|
|
294
312
|
#
|
|
295
313
|
# If a "history" of dependencies is present in the cache, each version of "history" will be
|
data/lib/sprockets/manifest.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'json'
|
|
2
3
|
require 'time'
|
|
3
4
|
|
|
4
5
|
require 'concurrent'
|
|
5
6
|
|
|
6
7
|
require 'sprockets/manifest_utils'
|
|
7
|
-
require 'sprockets/utils/gzip'
|
|
8
8
|
|
|
9
9
|
module Sprockets
|
|
10
10
|
# The Manifest logs the contents of assets compiled to a single directory. It
|
|
@@ -52,14 +52,8 @@ module Sprockets
|
|
|
52
52
|
@directory ||= File.dirname(@filename) if @filename
|
|
53
53
|
|
|
54
54
|
# If directory is given w/o filename, pick a random manifest location
|
|
55
|
-
@rename_filename = nil
|
|
56
55
|
if @directory && @filename.nil?
|
|
57
|
-
@filename = find_directory_manifest(@directory)
|
|
58
|
-
|
|
59
|
-
# If legacy manifest name autodetected, mark to rename on save
|
|
60
|
-
if File.basename(@filename).start_with?("manifest")
|
|
61
|
-
@rename_filename = File.join(@directory, generate_manifest_path)
|
|
62
|
-
end
|
|
56
|
+
@filename = find_directory_manifest(@directory, logger)
|
|
63
57
|
end
|
|
64
58
|
|
|
65
59
|
unless @directory && @filename
|
|
@@ -125,26 +119,15 @@ module Sprockets
|
|
|
125
119
|
|
|
126
120
|
return to_enum(__method__, *args) unless block_given?
|
|
127
121
|
|
|
128
|
-
paths, filters = args.flatten.partition { |arg| self.class.simple_logical_path?(arg) }
|
|
129
|
-
filters = filters.map { |arg| self.class.compile_match_filter(arg) }
|
|
130
|
-
|
|
131
122
|
environment = self.environment.cached
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
if filters.any?
|
|
140
|
-
environment.logical_paths do |logical_path, filename|
|
|
141
|
-
if filters.any? { |f| f.call(logical_path, filename) }
|
|
142
|
-
environment.find_all_linked_assets(filename) do |asset|
|
|
143
|
-
yield asset
|
|
144
|
-
end
|
|
123
|
+
promises = args.flatten.map do |path|
|
|
124
|
+
Concurrent::Promise.execute(executor: executor) do
|
|
125
|
+
environment.find_all_linked_assets(path) do |asset|
|
|
126
|
+
yield asset
|
|
145
127
|
end
|
|
146
128
|
end
|
|
147
129
|
end
|
|
130
|
+
promises.each(&:wait!)
|
|
148
131
|
|
|
149
132
|
nil
|
|
150
133
|
end
|
|
@@ -167,7 +150,7 @@ module Sprockets
|
|
|
167
150
|
end
|
|
168
151
|
end
|
|
169
152
|
|
|
170
|
-
# Compile
|
|
153
|
+
# Compile asset to directory. The asset is written to a
|
|
171
154
|
# fingerprinted filename like
|
|
172
155
|
# `application-2e8e9a7c6b0aafa0c9bdeec90ea30213.js`. An entry is
|
|
173
156
|
# also inserted into the manifest file.
|
|
@@ -179,14 +162,19 @@ module Sprockets
|
|
|
179
162
|
raise Error, "manifest requires environment for compilation"
|
|
180
163
|
end
|
|
181
164
|
|
|
182
|
-
filenames
|
|
183
|
-
|
|
184
|
-
concurrent_writers = []
|
|
165
|
+
filenames = []
|
|
166
|
+
concurrent_exporters = []
|
|
185
167
|
|
|
168
|
+
assets_to_export = Concurrent::Array.new
|
|
186
169
|
find(*args) do |asset|
|
|
170
|
+
assets_to_export << asset
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
assets_to_export.each do |asset|
|
|
174
|
+
mtime = Time.now.iso8601
|
|
187
175
|
files[asset.digest_path] = {
|
|
188
176
|
'logical_path' => asset.logical_path,
|
|
189
|
-
'mtime' =>
|
|
177
|
+
'mtime' => mtime,
|
|
190
178
|
'size' => asset.bytesize,
|
|
191
179
|
'digest' => asset.hexdigest,
|
|
192
180
|
|
|
@@ -197,38 +185,23 @@ module Sprockets
|
|
|
197
185
|
}
|
|
198
186
|
assets[asset.logical_path] = asset.digest_path
|
|
199
187
|
|
|
200
|
-
if alias_logical_path = self.class.compute_alias_logical_path(asset.logical_path)
|
|
201
|
-
assets[alias_logical_path] = asset.digest_path
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
target = File.join(dir, asset.digest_path)
|
|
205
|
-
|
|
206
|
-
if File.exist?(target)
|
|
207
|
-
logger.debug "Skipping #{target}, already exists"
|
|
208
|
-
else
|
|
209
|
-
logger.info "Writing #{target}"
|
|
210
|
-
write_file = Concurrent::Future.execute { asset.write_to target }
|
|
211
|
-
concurrent_writers << write_file
|
|
212
|
-
end
|
|
213
188
|
filenames << asset.filename
|
|
214
189
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
190
|
+
promise = nil
|
|
191
|
+
exporters_for_asset(asset) do |exporter|
|
|
192
|
+
next if exporter.skip?(logger)
|
|
218
193
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
write_file.wait! if write_file
|
|
225
|
-
gzip.compress(target)
|
|
194
|
+
if promise.nil?
|
|
195
|
+
promise = Concurrent::Promise.new(executor: executor) { exporter.call }
|
|
196
|
+
concurrent_exporters << promise.execute
|
|
197
|
+
else
|
|
198
|
+
concurrent_exporters << promise.then { exporter.call }
|
|
226
199
|
end
|
|
227
200
|
end
|
|
228
|
-
|
|
229
201
|
end
|
|
230
|
-
|
|
231
|
-
|
|
202
|
+
|
|
203
|
+
# make sure all exporters have finished before returning the main thread
|
|
204
|
+
concurrent_exporters.each(&:wait!)
|
|
232
205
|
save
|
|
233
206
|
|
|
234
207
|
filenames
|
|
@@ -295,18 +268,13 @@ module Sprockets
|
|
|
295
268
|
def clobber
|
|
296
269
|
FileUtils.rm_r(directory) if File.exist?(directory)
|
|
297
270
|
logger.info "Removed #{directory}"
|
|
271
|
+
# if we have an environment clear the cache too
|
|
272
|
+
environment.cache.clear if environment
|
|
298
273
|
nil
|
|
299
274
|
end
|
|
300
275
|
|
|
301
276
|
# Persist manfiest back to FS
|
|
302
277
|
def save
|
|
303
|
-
if @rename_filename
|
|
304
|
-
logger.info "Renaming #{@filename} to #{@rename_filename}"
|
|
305
|
-
FileUtils.mv(@filename, @rename_filename)
|
|
306
|
-
@filename = @rename_filename
|
|
307
|
-
@rename_filename = nil
|
|
308
|
-
end
|
|
309
|
-
|
|
310
278
|
data = json_encode(@data)
|
|
311
279
|
FileUtils.mkdir_p File.dirname(@filename)
|
|
312
280
|
PathUtils.atomic_write(@filename) do |f|
|
|
@@ -315,6 +283,36 @@ module Sprockets
|
|
|
315
283
|
end
|
|
316
284
|
|
|
317
285
|
private
|
|
286
|
+
|
|
287
|
+
# Given an asset, finds all exporters that
|
|
288
|
+
# match its mime-type.
|
|
289
|
+
#
|
|
290
|
+
# Will yield each expoter to the passed in block.
|
|
291
|
+
#
|
|
292
|
+
# array = []
|
|
293
|
+
# puts asset.content_type # => "application/javascript"
|
|
294
|
+
# exporters_for_asset(asset) do |exporter|
|
|
295
|
+
# array << exporter
|
|
296
|
+
# end
|
|
297
|
+
# # puts array => [Exporters::FileExporter, Exporters::ZlibExporter]
|
|
298
|
+
def exporters_for_asset(asset)
|
|
299
|
+
exporters = [Exporters::FileExporter]
|
|
300
|
+
|
|
301
|
+
environment.exporters.each do |mime_type, exporter_list|
|
|
302
|
+
next unless asset.content_type
|
|
303
|
+
next unless environment.match_mime_type? asset.content_type, mime_type
|
|
304
|
+
exporter_list.each do |exporter|
|
|
305
|
+
exporters << exporter
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
exporters.uniq!
|
|
310
|
+
|
|
311
|
+
exporters.each do |exporter|
|
|
312
|
+
yield exporter.new(asset: asset, environment: environment, directory: dir)
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
318
316
|
def json_decode(obj)
|
|
319
317
|
JSON.parse(obj, create_additions: false)
|
|
320
318
|
end
|
|
@@ -332,5 +330,9 @@ module Sprockets
|
|
|
332
330
|
logger
|
|
333
331
|
end
|
|
334
332
|
end
|
|
333
|
+
|
|
334
|
+
def executor
|
|
335
|
+
@executor ||= environment.export_concurrent ? :fast : :immediate
|
|
336
|
+
end
|
|
335
337
|
end
|
|
336
338
|
end
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'securerandom'
|
|
3
|
+
require 'logger'
|
|
2
4
|
|
|
3
5
|
module Sprockets
|
|
4
6
|
# Public: Manifest utilities.
|
|
@@ -6,7 +8,6 @@ module Sprockets
|
|
|
6
8
|
extend self
|
|
7
9
|
|
|
8
10
|
MANIFEST_RE = /^\.sprockets-manifest-[0-9a-f]{32}.json$/
|
|
9
|
-
LEGACY_MANIFEST_RE = /^manifest(-[0-9a-f]{32})?.json$/
|
|
10
11
|
|
|
11
12
|
# Public: Generate a new random manifest path.
|
|
12
13
|
#
|
|
@@ -33,12 +34,14 @@ module Sprockets
|
|
|
33
34
|
# # => "/app/public/assets/.sprockets-manifest-abc123.json"
|
|
34
35
|
#
|
|
35
36
|
# Returns String filename.
|
|
36
|
-
def find_directory_manifest(dirname)
|
|
37
|
+
def find_directory_manifest(dirname, logger = Logger.new($stderr))
|
|
37
38
|
entries = File.directory?(dirname) ? Dir.entries(dirname) : []
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
manifest_entries = entries.select { |e| e =~ MANIFEST_RE }
|
|
40
|
+
if manifest_entries.length > 1
|
|
41
|
+
manifest_entries.sort!
|
|
42
|
+
logger.warn("Found multiple manifests: #{manifest_entries}. Choosing the first alphabetically: #{manifest_entries.first}")
|
|
43
|
+
end
|
|
44
|
+
entry = manifest_entries.first || generate_manifest_path
|
|
42
45
|
File.join(dirname, entry)
|
|
43
46
|
end
|
|
44
47
|
end
|
data/lib/sprockets/mime.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'sprockets/encoding_utils'
|
|
2
3
|
require 'sprockets/http_utils'
|
|
3
4
|
require 'sprockets/utils'
|
|
@@ -36,29 +37,18 @@ module Sprockets
|
|
|
36
37
|
|
|
37
38
|
# Public: Register a new mime type.
|
|
38
39
|
#
|
|
39
|
-
# mime_type
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
# See EncodingUtils.
|
|
40
|
+
# mime_type - String MIME Type
|
|
41
|
+
# extensions - Array of String extnames
|
|
42
|
+
# charset - Proc/Method that detects the charset of a file.
|
|
43
|
+
# See EncodingUtils.
|
|
44
44
|
#
|
|
45
45
|
# Returns nothing.
|
|
46
|
-
def register_mime_type(mime_type,
|
|
47
|
-
|
|
48
|
-
if options.is_a?(String)
|
|
49
|
-
options = { extensions: [options] }
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
extnames = Array(options[:extensions]).map { |extname|
|
|
53
|
-
Sprockets::Utils.normalize_extension(extname)
|
|
54
|
-
}
|
|
46
|
+
def register_mime_type(mime_type, extensions: [], charset: nil)
|
|
47
|
+
extnames = Array(extensions)
|
|
55
48
|
|
|
56
|
-
charset = options[:charset]
|
|
57
49
|
charset ||= :default if mime_type.start_with?('text/')
|
|
58
50
|
charset = EncodingUtils::CHARSET_DETECT[charset] if charset.is_a?(Symbol)
|
|
59
51
|
|
|
60
|
-
self.computed_config = {}
|
|
61
|
-
|
|
62
52
|
self.config = hash_reassoc(config, :mime_exts) do |mime_exts|
|
|
63
53
|
extnames.each do |extname|
|
|
64
54
|
mime_exts[extname] = mime_type
|
|
@@ -97,34 +87,10 @@ module Sprockets
|
|
|
97
87
|
data = File.binread(filename)
|
|
98
88
|
|
|
99
89
|
if detect = mime_type_charset_detecter(content_type)
|
|
100
|
-
detect.call(data).encode(Encoding::UTF_8, :
|
|
90
|
+
detect.call(data).encode(Encoding::UTF_8, universal_newline: true)
|
|
101
91
|
else
|
|
102
92
|
data
|
|
103
93
|
end
|
|
104
94
|
end
|
|
105
|
-
|
|
106
|
-
private
|
|
107
|
-
def extname_map
|
|
108
|
-
self.computed_config[:_extnames] ||= compute_extname_map
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def compute_extname_map
|
|
112
|
-
graph = {}
|
|
113
|
-
|
|
114
|
-
([nil] + pipelines.keys.map(&:to_s)).each do |pipeline|
|
|
115
|
-
pipeline_extname = ".#{pipeline}" if pipeline
|
|
116
|
-
([[nil, nil]] + config[:mime_exts].to_a).each do |format_extname, format_type|
|
|
117
|
-
4.times do |n|
|
|
118
|
-
config[:engines].keys.permutation(n).each do |engine_extnames|
|
|
119
|
-
key = "#{pipeline_extname}#{format_extname}#{engine_extnames.join}"
|
|
120
|
-
type = format_type || config[:engine_mime_types][engine_extnames.first]
|
|
121
|
-
graph[key] = {type: type, engines: engine_extnames, pipeline: pipeline}
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
graph
|
|
128
|
-
end
|
|
129
95
|
end
|
|
130
96
|
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
module Sprockets
|
|
5
|
+
module Npm
|
|
6
|
+
# Internal: Override resolve_alternates to install package.json behavior.
|
|
7
|
+
#
|
|
8
|
+
# load_path - String environment path
|
|
9
|
+
# logical_path - String path relative to base
|
|
10
|
+
#
|
|
11
|
+
# Returns candiate filenames.
|
|
12
|
+
def resolve_alternates(load_path, logical_path)
|
|
13
|
+
candidates, deps = super
|
|
14
|
+
|
|
15
|
+
dirname = File.join(load_path, logical_path)
|
|
16
|
+
|
|
17
|
+
if directory?(dirname)
|
|
18
|
+
filename = File.join(dirname, 'package.json')
|
|
19
|
+
|
|
20
|
+
if self.file?(filename)
|
|
21
|
+
deps << build_file_digest_uri(filename)
|
|
22
|
+
read_package_directives(dirname, filename) do |path|
|
|
23
|
+
if file?(path)
|
|
24
|
+
candidates << path
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
return candidates, deps
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Internal: Read package.json's main and style directives.
|
|
34
|
+
#
|
|
35
|
+
# dirname - String path to component directory.
|
|
36
|
+
# filename - String path to package.json.
|
|
37
|
+
#
|
|
38
|
+
# Returns nothing.
|
|
39
|
+
def read_package_directives(dirname, filename)
|
|
40
|
+
package = JSON.parse(File.read(filename), create_additions: false)
|
|
41
|
+
|
|
42
|
+
case package['main']
|
|
43
|
+
when String
|
|
44
|
+
yield File.expand_path(package['main'], dirname)
|
|
45
|
+
when nil
|
|
46
|
+
yield File.expand_path('index.js', dirname)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
yield File.expand_path(package['style'], dirname) if package['style']
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|