sprockets 2.2.3 → 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 +5 -5
- data/CHANGELOG.md +68 -0
- data/README.md +482 -255
- data/bin/sprockets +20 -7
- data/lib/rake/sprocketstask.rb +28 -15
- data/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
- data/lib/sprockets/asset.rb +142 -207
- data/lib/sprockets/autoload/babel.rb +8 -0
- data/lib/sprockets/autoload/closure.rb +8 -0
- data/lib/sprockets/autoload/coffee_script.rb +8 -0
- data/lib/sprockets/autoload/eco.rb +8 -0
- data/lib/sprockets/autoload/ejs.rb +8 -0
- data/lib/sprockets/autoload/jsminc.rb +8 -0
- data/lib/sprockets/autoload/sass.rb +8 -0
- data/lib/sprockets/autoload/sassc.rb +8 -0
- data/lib/sprockets/autoload/uglifier.rb +8 -0
- data/lib/sprockets/autoload/yui.rb +8 -0
- data/lib/sprockets/autoload/zopfli.rb +7 -0
- data/lib/sprockets/autoload.rb +16 -0
- data/lib/sprockets/babel_processor.rb +66 -0
- data/lib/sprockets/base.rb +89 -249
- data/lib/sprockets/bower.rb +61 -0
- data/lib/sprockets/bundle.rb +105 -0
- data/lib/sprockets/cache/file_store.rb +190 -14
- data/lib/sprockets/cache/memory_store.rb +75 -0
- data/lib/sprockets/cache/null_store.rb +54 -0
- data/lib/sprockets/cache.rb +271 -0
- data/lib/sprockets/cached_environment.rb +64 -0
- data/lib/sprockets/closure_compressor.rb +48 -0
- data/lib/sprockets/coffee_script_processor.rb +39 -0
- data/lib/sprockets/compressing.rb +134 -0
- data/lib/sprockets/configuration.rb +79 -0
- data/lib/sprockets/context.rb +204 -135
- data/lib/sprockets/dependencies.rb +74 -0
- data/lib/sprockets/digest_utils.rb +200 -0
- data/lib/sprockets/directive_processor.rb +224 -216
- data/lib/sprockets/eco_processor.rb +33 -0
- data/lib/sprockets/ejs_processor.rb +32 -0
- data/lib/sprockets/encoding_utils.rb +262 -0
- data/lib/sprockets/environment.rb +23 -68
- data/lib/sprockets/erb_processor.rb +37 -0
- data/lib/sprockets/errors.rb +6 -13
- 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 +16 -0
- data/lib/sprockets/http_utils.rb +135 -0
- data/lib/sprockets/jsminc_compressor.rb +32 -0
- data/lib/sprockets/jst_processor.rb +36 -19
- data/lib/sprockets/loader.rb +343 -0
- data/lib/sprockets/manifest.rb +231 -96
- data/lib/sprockets/manifest_utils.rb +48 -0
- data/lib/sprockets/mime.rb +80 -32
- data/lib/sprockets/npm.rb +52 -0
- data/lib/sprockets/path_dependency_utils.rb +77 -0
- data/lib/sprockets/path_digest_utils.rb +48 -0
- data/lib/sprockets/path_utils.rb +367 -0
- data/lib/sprockets/paths.rb +82 -0
- data/lib/sprockets/preprocessors/default_source_map.rb +49 -0
- data/lib/sprockets/processing.rb +140 -192
- data/lib/sprockets/processor_utils.rb +169 -0
- data/lib/sprockets/resolve.rb +295 -0
- data/lib/sprockets/sass_cache_store.rb +30 -0
- data/lib/sprockets/sass_compressor.rb +63 -0
- data/lib/sprockets/sass_functions.rb +3 -0
- data/lib/sprockets/sass_importer.rb +3 -0
- data/lib/sprockets/sass_processor.rb +313 -0
- data/lib/sprockets/sassc_compressor.rb +56 -0
- data/lib/sprockets/sassc_processor.rb +297 -0
- data/lib/sprockets/server.rb +138 -90
- data/lib/sprockets/source_map_processor.rb +66 -0
- data/lib/sprockets/source_map_utils.rb +483 -0
- data/lib/sprockets/transformers.rb +173 -0
- data/lib/sprockets/uglifier_compressor.rb +66 -0
- data/lib/sprockets/unloaded_asset.rb +139 -0
- data/lib/sprockets/uri_tar.rb +99 -0
- data/lib/sprockets/uri_utils.rb +191 -0
- data/lib/sprockets/utils/gzip.rb +99 -0
- data/lib/sprockets/utils.rb +186 -53
- data/lib/sprockets/version.rb +2 -1
- data/lib/sprockets/yui_compressor.rb +56 -0
- data/lib/sprockets.rb +217 -52
- metadata +250 -59
- data/LICENSE +0 -21
- data/lib/sprockets/asset_attributes.rb +0 -126
- data/lib/sprockets/bundled_asset.rb +0 -79
- data/lib/sprockets/caching.rb +0 -96
- data/lib/sprockets/charset_normalizer.rb +0 -41
- data/lib/sprockets/eco_template.rb +0 -38
- data/lib/sprockets/ejs_template.rb +0 -37
- data/lib/sprockets/engines.rb +0 -74
- data/lib/sprockets/index.rb +0 -99
- data/lib/sprockets/processed_asset.rb +0 -152
- data/lib/sprockets/processor.rb +0 -32
- data/lib/sprockets/safety_colons.rb +0 -28
- data/lib/sprockets/static_asset.rb +0 -57
- data/lib/sprockets/trail.rb +0 -90
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Sprockets
|
3
|
+
module Autoload
|
4
|
+
autoload :Babel, 'sprockets/autoload/babel'
|
5
|
+
autoload :Closure, 'sprockets/autoload/closure'
|
6
|
+
autoload :CoffeeScript, 'sprockets/autoload/coffee_script'
|
7
|
+
autoload :Eco, 'sprockets/autoload/eco'
|
8
|
+
autoload :EJS, 'sprockets/autoload/ejs'
|
9
|
+
autoload :JSMinC, 'sprockets/autoload/jsminc'
|
10
|
+
autoload :Sass, 'sprockets/autoload/sass'
|
11
|
+
autoload :SassC, 'sprockets/autoload/sassc'
|
12
|
+
autoload :Uglifier, 'sprockets/autoload/uglifier'
|
13
|
+
autoload :YUI, 'sprockets/autoload/yui'
|
14
|
+
autoload :Zopfli, 'sprockets/autoload/zopfli'
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'sprockets/autoload'
|
3
|
+
require 'sprockets/path_utils'
|
4
|
+
require 'sprockets/source_map_utils'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module Sprockets
|
8
|
+
class BabelProcessor
|
9
|
+
VERSION = '1'
|
10
|
+
|
11
|
+
def self.instance
|
12
|
+
@instance ||= new
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.call(input)
|
16
|
+
instance.call(input)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.cache_key
|
20
|
+
instance.cache_key
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :cache_key
|
24
|
+
|
25
|
+
def initialize(options = {})
|
26
|
+
@options = options.merge({
|
27
|
+
'blacklist' => (options['blacklist'] || []) + ['useStrict'],
|
28
|
+
'sourceMap' => true
|
29
|
+
}).freeze
|
30
|
+
|
31
|
+
@cache_key = [
|
32
|
+
self.class.name,
|
33
|
+
Autoload::Babel::Transpiler::VERSION,
|
34
|
+
Autoload::Babel::Source::VERSION,
|
35
|
+
VERSION,
|
36
|
+
@options
|
37
|
+
].freeze
|
38
|
+
end
|
39
|
+
|
40
|
+
def call(input)
|
41
|
+
data = input[:data]
|
42
|
+
|
43
|
+
result = input[:cache].fetch(@cache_key + [input[:filename]] + [data]) do
|
44
|
+
opts = {
|
45
|
+
'moduleRoot' => nil,
|
46
|
+
'filename' => input[:filename],
|
47
|
+
'filenameRelative' => PathUtils.split_subpath(input[:load_path], input[:filename]),
|
48
|
+
'sourceFileName' => File.basename(input[:filename]),
|
49
|
+
'sourceMapTarget' => input[:filename]
|
50
|
+
}.merge(@options)
|
51
|
+
|
52
|
+
if opts['moduleIds'] && opts['moduleRoot']
|
53
|
+
opts['moduleId'] ||= File.join(opts['moduleRoot'], input[:name])
|
54
|
+
elsif opts['moduleIds']
|
55
|
+
opts['moduleId'] ||= input[:name]
|
56
|
+
end
|
57
|
+
Autoload::Babel::Transpiler.transform(data, opts)
|
58
|
+
end
|
59
|
+
|
60
|
+
map = SourceMapUtils.format_source_map(result["map"], input)
|
61
|
+
map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
|
62
|
+
|
63
|
+
{ data: result['code'], map: map }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/sprockets/base.rb
CHANGED
@@ -1,89 +1,41 @@
|
|
1
|
-
|
2
|
-
require 'sprockets/
|
3
|
-
require 'sprockets/
|
4
|
-
require 'sprockets/
|
5
|
-
require 'sprockets/
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'sprockets/asset'
|
3
|
+
require 'sprockets/bower'
|
4
|
+
require 'sprockets/cache'
|
5
|
+
require 'sprockets/configuration'
|
6
|
+
require 'sprockets/digest_utils'
|
7
|
+
require 'sprockets/errors'
|
8
|
+
require 'sprockets/loader'
|
9
|
+
require 'sprockets/npm'
|
10
|
+
require 'sprockets/path_dependency_utils'
|
11
|
+
require 'sprockets/path_digest_utils'
|
12
|
+
require 'sprockets/path_utils'
|
13
|
+
require 'sprockets/resolve'
|
6
14
|
require 'sprockets/server'
|
7
|
-
require 'sprockets/
|
8
|
-
require 'sprockets/
|
9
|
-
require 'pathname'
|
15
|
+
require 'sprockets/source_map_utils'
|
16
|
+
require 'sprockets/uri_tar'
|
10
17
|
|
11
18
|
module Sprockets
|
12
|
-
# `Base` class for `Environment` and `Index`.
|
13
|
-
class Base
|
14
|
-
include Caching, Processing, Server, Trail
|
15
|
-
|
16
|
-
# Returns a `Digest` implementation class.
|
17
|
-
#
|
18
|
-
# Defaults to `Digest::MD5`.
|
19
|
-
attr_reader :digest_class
|
20
|
-
|
21
|
-
# Assign a `Digest` implementation class. This maybe any Ruby
|
22
|
-
# `Digest::` implementation such as `Digest::MD5` or
|
23
|
-
# `Digest::SHA1`.
|
24
|
-
#
|
25
|
-
# environment.digest_class = Digest::SHA1
|
26
|
-
#
|
27
|
-
def digest_class=(klass)
|
28
|
-
expire_index!
|
29
|
-
@digest_class = klass
|
30
|
-
end
|
31
|
-
|
32
|
-
# The `Environment#version` is a custom value used for manually
|
33
|
-
# expiring all asset caches.
|
34
|
-
#
|
35
|
-
# Sprockets is able to track most file and directory changes and
|
36
|
-
# will take care of expiring the cache for you. However, its
|
37
|
-
# impossible to know when any custom helpers change that you mix
|
38
|
-
# into the `Context`.
|
39
|
-
#
|
40
|
-
# It would be wise to increment this value anytime you make a
|
41
|
-
# configuration change to the `Environment` object.
|
42
|
-
attr_reader :version
|
43
19
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
# Returns a `Digest` instance for the `Environment`.
|
54
|
-
#
|
55
|
-
# This value serves two purposes. If two `Environment`s have the
|
56
|
-
# same digest value they can be treated as equal. This is more
|
57
|
-
# useful for comparing environment states between processes rather
|
58
|
-
# than in the same. Two equal `Environment`s can share the same
|
59
|
-
# cached assets.
|
60
|
-
#
|
61
|
-
# The value also provides a seed digest for all `Asset`
|
62
|
-
# digests. Any change in the environment digest will affect all of
|
63
|
-
# its assets.
|
64
|
-
def digest
|
65
|
-
# Compute the initial digest using the implementation class. The
|
66
|
-
# Sprockets release version and custom environment version are
|
67
|
-
# mixed in. So any new releases will affect all your assets.
|
68
|
-
@digest ||= digest_class.new.update(VERSION).update(version.to_s)
|
69
|
-
|
70
|
-
# Returned a dupped copy so the caller can safely mutate it with `.update`
|
71
|
-
@digest.dup
|
20
|
+
class DoubleLinkError < Sprockets::Error
|
21
|
+
def initialize(parent_filename:, logical_path:, last_filename:, filename:)
|
22
|
+
super <<~MSG
|
23
|
+
Multiple files with the same output path cannot be linked (#{logical_path.inspect})
|
24
|
+
In #{parent_filename.inspect} these files were linked:
|
25
|
+
- #{last_filename}
|
26
|
+
- #{filename}
|
27
|
+
MSG
|
72
28
|
end
|
29
|
+
end
|
73
30
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
# include MyHelpers
|
83
|
-
# def asset_url; end
|
84
|
-
# end
|
85
|
-
#
|
86
|
-
attr_reader :context_class
|
31
|
+
# `Base` class for `Environment` and `CachedEnvironment`.
|
32
|
+
class Base
|
33
|
+
include PathUtils, PathDependencyUtils, PathDigestUtils, DigestUtils, SourceMapUtils
|
34
|
+
include Configuration
|
35
|
+
include Server
|
36
|
+
include Resolve, Loader
|
37
|
+
include Bower
|
38
|
+
include Npm
|
87
39
|
|
88
40
|
# Get persistent cache store
|
89
41
|
attr_reader :cache
|
@@ -94,79 +46,69 @@ module Sprockets
|
|
94
46
|
# setters. Either `get(key)`/`set(key, value)`,
|
95
47
|
# `[key]`/`[key]=value`, `read(key)`/`write(key, value)`.
|
96
48
|
def cache=(cache)
|
97
|
-
|
98
|
-
@cache = cache
|
49
|
+
@cache = Cache.new(cache, logger)
|
99
50
|
end
|
100
51
|
|
101
|
-
# Return an `
|
102
|
-
def
|
52
|
+
# Return an `CachedEnvironment`. Must be implemented by the subclass.
|
53
|
+
def cached
|
103
54
|
raise NotImplementedError
|
104
55
|
end
|
56
|
+
alias_method :index, :cached
|
105
57
|
|
106
|
-
|
107
|
-
# Define `default_external_encoding` accessor on 1.9.
|
108
|
-
# Defaults to UTF-8.
|
109
|
-
attr_accessor :default_external_encoding
|
110
|
-
end
|
111
|
-
|
112
|
-
# Works like `Dir.entries`.
|
58
|
+
# Internal: Compute digest for path.
|
113
59
|
#
|
114
|
-
#
|
115
|
-
def entries(pathname)
|
116
|
-
trail.entries(pathname)
|
117
|
-
end
|
118
|
-
|
119
|
-
# Works like `File.stat`.
|
120
|
-
#
|
121
|
-
# Subclasses may cache this method.
|
122
|
-
def stat(path)
|
123
|
-
trail.stat(path)
|
124
|
-
end
|
125
|
-
|
126
|
-
# Read and compute digest of filename.
|
60
|
+
# path - String filename or directory path.
|
127
61
|
#
|
128
|
-
#
|
62
|
+
# Returns a String digest or nil.
|
129
63
|
def file_digest(path)
|
130
64
|
if stat = self.stat(path)
|
131
|
-
#
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
#
|
136
|
-
|
137
|
-
|
138
|
-
|
65
|
+
# Caveat: Digests are cached by the path's current mtime. Its possible
|
66
|
+
# for a files contents to have changed and its mtime to have been
|
67
|
+
# negligently reset thus appearing as if the file hasn't changed on
|
68
|
+
# disk. Also, the mtime is only read to the nearest second. It's
|
69
|
+
# also possible the file was updated more than once in a given second.
|
70
|
+
key = UnloadedAsset.new(path, self).file_digest_key(stat.mtime.to_i)
|
71
|
+
cache.fetch(key) do
|
72
|
+
self.stat_digest(path, stat)
|
139
73
|
end
|
140
74
|
end
|
141
75
|
end
|
142
76
|
|
143
|
-
#
|
144
|
-
def
|
145
|
-
|
77
|
+
# Find asset by logical path or expanded path.
|
78
|
+
def find_asset(*args, **options)
|
79
|
+
uri, _ = resolve(*args, **options)
|
80
|
+
if uri
|
81
|
+
load(uri)
|
82
|
+
end
|
146
83
|
end
|
147
84
|
|
148
|
-
|
149
|
-
|
150
|
-
attributes_for(path).content_type
|
151
|
-
end
|
85
|
+
def find_all_linked_assets(*args)
|
86
|
+
return to_enum(__method__, *args) unless block_given?
|
152
87
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
88
|
+
parent_asset = asset = find_asset(*args)
|
89
|
+
return unless asset
|
90
|
+
|
91
|
+
yield asset
|
92
|
+
stack = asset.links.to_a
|
93
|
+
linked_paths = {}
|
94
|
+
|
95
|
+
while uri = stack.shift
|
96
|
+
yield asset = load(uri)
|
157
97
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
98
|
+
last_filename = linked_paths[asset.logical_path]
|
99
|
+
if last_filename && last_filename != asset.filename
|
100
|
+
raise DoubleLinkError.new(
|
101
|
+
parent_filename: parent_asset.filename,
|
102
|
+
last_filename: last_filename,
|
103
|
+
logical_path: asset.logical_path,
|
104
|
+
filename: asset.filename
|
105
|
+
)
|
166
106
|
end
|
107
|
+
linked_paths[asset.logical_path] = asset.filename
|
108
|
+
stack = asset.links.to_a + stack
|
167
109
|
end
|
168
110
|
|
169
|
-
|
111
|
+
nil
|
170
112
|
end
|
171
113
|
|
172
114
|
# Preferred `find_asset` shorthand.
|
@@ -177,131 +119,29 @@ module Sprockets
|
|
177
119
|
find_asset(*args)
|
178
120
|
end
|
179
121
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
paths << path
|
188
|
-
|
189
|
-
if stat(path).directory?
|
190
|
-
each_entry(path) do |subpath|
|
191
|
-
paths << subpath
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
paths.sort_by(&:to_s).each(&block)
|
197
|
-
|
198
|
-
nil
|
199
|
-
end
|
200
|
-
|
201
|
-
def each_file
|
202
|
-
return to_enum(__method__) unless block_given?
|
203
|
-
paths.each do |root|
|
204
|
-
each_entry(root) do |path|
|
205
|
-
if !stat(path).directory?
|
206
|
-
yield path
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
|
-
nil
|
211
|
-
end
|
212
|
-
|
213
|
-
def each_logical_path(*args)
|
214
|
-
return to_enum(__method__, *args) unless block_given?
|
215
|
-
filters = args.flatten
|
216
|
-
files = {}
|
217
|
-
each_file do |filename|
|
218
|
-
if logical_path = logical_path_for_filename(filename, filters)
|
219
|
-
yield logical_path unless files[logical_path]
|
220
|
-
files[logical_path] = true
|
221
|
-
end
|
122
|
+
# Find asset by logical path or expanded path.
|
123
|
+
#
|
124
|
+
# If the asset is not found an error will be raised.
|
125
|
+
def find_asset!(*args)
|
126
|
+
uri, _ = resolve!(*args)
|
127
|
+
if uri
|
128
|
+
load(uri)
|
222
129
|
end
|
223
|
-
nil
|
224
130
|
end
|
225
131
|
|
226
132
|
# Pretty inspect
|
227
133
|
def inspect
|
228
134
|
"#<#{self.class}:0x#{object_id.to_s(16)} " +
|
229
135
|
"root=#{root.to_s.inspect}, " +
|
230
|
-
"paths=#{paths.inspect}
|
231
|
-
"digest=#{digest.to_s.inspect}" +
|
232
|
-
">"
|
136
|
+
"paths=#{paths.inspect}>"
|
233
137
|
end
|
234
138
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
raise NotImplementedError
|
239
|
-
end
|
240
|
-
|
241
|
-
def build_asset(logical_path, pathname, options)
|
242
|
-
pathname = Pathname.new(pathname)
|
243
|
-
|
244
|
-
# If there are any processors to run on the pathname, use
|
245
|
-
# `BundledAsset`. Otherwise use `StaticAsset` and treat is as binary.
|
246
|
-
if attributes_for(pathname).processors.any?
|
247
|
-
if options[:bundle] == false
|
248
|
-
circular_call_protection(pathname.to_s) do
|
249
|
-
ProcessedAsset.new(index, logical_path, pathname)
|
250
|
-
end
|
251
|
-
else
|
252
|
-
BundledAsset.new(index, logical_path, pathname)
|
253
|
-
end
|
254
|
-
else
|
255
|
-
StaticAsset.new(index, logical_path, pathname)
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
def cache_key_for(path, options)
|
260
|
-
"#{path}:#{options[:bundle] ? '1' : '0'}"
|
261
|
-
end
|
262
|
-
|
263
|
-
def circular_call_protection(path)
|
264
|
-
reset = Thread.current[:sprockets_circular_calls].nil?
|
265
|
-
calls = Thread.current[:sprockets_circular_calls] ||= Set.new
|
266
|
-
if calls.include?(path)
|
267
|
-
raise CircularDependencyError, "#{path} has already been required"
|
268
|
-
end
|
269
|
-
calls << path
|
270
|
-
yield
|
271
|
-
ensure
|
272
|
-
Thread.current[:sprockets_circular_calls] = nil if reset
|
273
|
-
end
|
274
|
-
|
275
|
-
def logical_path_for_filename(filename, filters)
|
276
|
-
logical_path = attributes_for(filename).logical_path.to_s
|
277
|
-
|
278
|
-
if matches_filter(filters, logical_path)
|
279
|
-
return logical_path
|
280
|
-
end
|
281
|
-
|
282
|
-
# If filename is an index file, retest with alias
|
283
|
-
if File.basename(logical_path)[/[^\.]+/, 0] == 'index'
|
284
|
-
path = logical_path.sub(/\/index\./, '.')
|
285
|
-
if matches_filter(filters, path)
|
286
|
-
return path
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
nil
|
291
|
-
end
|
292
|
-
|
293
|
-
def matches_filter(filters, filename)
|
294
|
-
return true if filters.empty?
|
139
|
+
def compress_from_root(uri)
|
140
|
+
URITar.new(uri, self).compress
|
141
|
+
end
|
295
142
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
elsif filter.respond_to?(:call)
|
300
|
-
filter.call(filename)
|
301
|
-
else
|
302
|
-
File.fnmatch(filter.to_s, filename)
|
303
|
-
end
|
304
|
-
end
|
305
|
-
end
|
143
|
+
def expand_from_root(uri)
|
144
|
+
URITar.new(uri, self).expand
|
145
|
+
end
|
306
146
|
end
|
307
147
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Sprockets
|
5
|
+
module Bower
|
6
|
+
# Internal: All supported bower.json files.
|
7
|
+
#
|
8
|
+
# https://github.com/bower/json/blob/0.4.0/lib/json.js#L7
|
9
|
+
POSSIBLE_BOWER_JSONS = ['bower.json', 'component.json', '.bower.json']
|
10
|
+
|
11
|
+
# Internal: Override resolve_alternates to install bower.json behavior.
|
12
|
+
#
|
13
|
+
# load_path - String environment path
|
14
|
+
# logical_path - String path relative to base
|
15
|
+
#
|
16
|
+
# Returns candiate filenames.
|
17
|
+
def resolve_alternates(load_path, logical_path)
|
18
|
+
candidates, deps = super
|
19
|
+
|
20
|
+
# bower.json can only be nested one level deep
|
21
|
+
if !logical_path.index('/'.freeze)
|
22
|
+
dirname = File.join(load_path, logical_path)
|
23
|
+
|
24
|
+
if directory?(dirname)
|
25
|
+
filenames = POSSIBLE_BOWER_JSONS.map { |basename| File.join(dirname, basename) }
|
26
|
+
filename = filenames.detect { |fn| self.file?(fn) }
|
27
|
+
|
28
|
+
if filename
|
29
|
+
deps << build_file_digest_uri(filename)
|
30
|
+
read_bower_main(dirname, filename) do |path|
|
31
|
+
if file?(path)
|
32
|
+
candidates << path
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
return candidates, deps
|
40
|
+
end
|
41
|
+
|
42
|
+
# Internal: Read bower.json's main directive.
|
43
|
+
#
|
44
|
+
# dirname - String path to component directory.
|
45
|
+
# filename - String path to bower.json.
|
46
|
+
#
|
47
|
+
# Returns nothing.
|
48
|
+
def read_bower_main(dirname, filename)
|
49
|
+
bower = JSON.parse(File.read(filename), create_additions: false)
|
50
|
+
|
51
|
+
case bower['main']
|
52
|
+
when String
|
53
|
+
yield File.expand_path(bower['main'], dirname)
|
54
|
+
when Array
|
55
|
+
bower['main'].each do |name|
|
56
|
+
yield File.expand_path(name, dirname)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'set'
|
3
|
+
require 'sprockets/utils'
|
4
|
+
require 'sprockets/uri_utils'
|
5
|
+
|
6
|
+
module Sprockets
|
7
|
+
# Internal: Bundle processor takes a single file asset and prepends all the
|
8
|
+
# `:required` URIs to the contents.
|
9
|
+
#
|
10
|
+
# Uses pipeline metadata:
|
11
|
+
#
|
12
|
+
# :required - Ordered Set of asset URIs to prepend
|
13
|
+
# :stubbed - Set of asset URIs to substract from the required set.
|
14
|
+
#
|
15
|
+
# Also see DirectiveProcessor.
|
16
|
+
class Bundle
|
17
|
+
def self.call(input)
|
18
|
+
env = input[:environment]
|
19
|
+
type = input[:content_type]
|
20
|
+
input[:links] ||= Set.new
|
21
|
+
dependencies = Set.new(input[:metadata][:dependencies])
|
22
|
+
|
23
|
+
processed_uri, deps = env.resolve(input[:filename], accept: type, pipeline: :self)
|
24
|
+
dependencies.merge(deps)
|
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
|
+
|
41
|
+
find_required = proc { |uri| env.load(uri).metadata[:required] }
|
42
|
+
required = Utils.dfs(processed_uri, &find_required)
|
43
|
+
stubbed = Utils.dfs(env.load(processed_uri).metadata[:stubbed], &find_required)
|
44
|
+
required.subtract(stubbed)
|
45
|
+
dedup(required)
|
46
|
+
assets = required.map { |uri| env.load(uri) }
|
47
|
+
|
48
|
+
(required + stubbed).each do |uri|
|
49
|
+
dependencies.merge(env.load(uri).metadata[:dependencies])
|
50
|
+
end
|
51
|
+
|
52
|
+
reducers = Hash[env.match_mime_type_keys(env.config[:bundle_reducers], type).flat_map(&:to_a)]
|
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)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Internal: Run bundle reducers on set of Assets producing a reduced
|
73
|
+
# metadata Hash.
|
74
|
+
#
|
75
|
+
# filename - String bundle filename
|
76
|
+
# assets - Array of Assets
|
77
|
+
# reducers - Array of [initial, reducer_proc] pairs
|
78
|
+
#
|
79
|
+
# Returns reduced asset metadata Hash.
|
80
|
+
def self.process_bundle_reducers(input, assets, reducers)
|
81
|
+
initial = {}
|
82
|
+
reducers.each do |k, (v, _)|
|
83
|
+
if v.respond_to?(:call)
|
84
|
+
initial[k] = v.call(input)
|
85
|
+
elsif !v.nil?
|
86
|
+
initial[k] = v
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
assets.reduce(initial) do |h, asset|
|
91
|
+
reducers.each do |k, (_, block)|
|
92
|
+
value = k == :data ? asset.source : asset.metadata[k]
|
93
|
+
if h.key?(k)
|
94
|
+
if !value.nil?
|
95
|
+
h[k] = block.call(h[k], value)
|
96
|
+
end
|
97
|
+
else
|
98
|
+
h[k] = value
|
99
|
+
end
|
100
|
+
end
|
101
|
+
h
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|