sprockets 2.6.0 → 4.2.2
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 +7 -0
- data/CHANGELOG.md +118 -0
- data/{LICENSE → MIT-LICENSE} +2 -2
- data/README.md +541 -289
- data/bin/sprockets +20 -7
- data/lib/rake/sprocketstask.rb +34 -17
- data/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
- data/lib/sprockets/asset.rb +158 -210
- 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 -378
- 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 +84 -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 +166 -150
- data/lib/sprockets/dependencies.rb +74 -0
- data/lib/sprockets/digest_utils.rb +197 -0
- data/lib/sprockets/directive_processor.rb +241 -215
- data/lib/sprockets/eco_processor.rb +33 -0
- data/lib/sprockets/ejs_processor.rb +32 -0
- data/lib/sprockets/encoding_utils.rb +261 -0
- data/lib/sprockets/environment.rb +23 -64
- data/lib/sprockets/erb_processor.rb +43 -0
- data/lib/sprockets/errors.rb +5 -13
- data/lib/sprockets/exporters/base.rb +71 -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 +347 -0
- data/lib/sprockets/manifest.rb +228 -112
- data/lib/sprockets/manifest_utils.rb +48 -0
- data/lib/sprockets/mime.rb +78 -31
- 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 +43 -19
- data/lib/sprockets/preprocessors/default_source_map.rb +49 -0
- data/lib/sprockets/processing.rb +146 -164
- data/lib/sprockets/processor_utils.rb +170 -0
- data/lib/sprockets/resolve.rb +295 -0
- data/lib/sprockets/sass_cache_store.rb +20 -15
- data/lib/sprockets/sass_compressor.rb +55 -10
- data/lib/sprockets/sass_functions.rb +3 -70
- data/lib/sprockets/sass_importer.rb +3 -29
- 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 +159 -91
- 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 +194 -0
- data/lib/sprockets/utils/gzip.rb +99 -0
- data/lib/sprockets/utils.rb +193 -52
- data/lib/sprockets/version.rb +2 -1
- data/lib/sprockets/yui_compressor.rb +56 -0
- data/lib/sprockets.rb +217 -75
- metadata +272 -117
- data/lib/sprockets/asset_attributes.rb +0 -131
- data/lib/sprockets/bundled_asset.rb +0 -80
- 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/sass_template.rb +0 -60
- data/lib/sprockets/scss_template.rb +0 -13
- data/lib/sprockets/static_asset.rb +0 -58
|
@@ -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/
|
|
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'
|
|
4
7
|
require 'sprockets/errors'
|
|
5
|
-
require 'sprockets/
|
|
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 '
|
|
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, Paths, Mime, Processing, Engines, Server
|
|
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
|
-
|
|
44
|
-
# Assign an environment version.
|
|
45
|
-
#
|
|
46
|
-
# environment.version = '2.0'
|
|
47
|
-
#
|
|
48
|
-
def version=(version)
|
|
49
|
-
expire_index!
|
|
50
|
-
@version = version
|
|
51
|
-
end
|
|
52
19
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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,343 +46,102 @@ 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
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def prepend_path(path)
|
|
102
|
-
# Overrides the global behavior to expire the index
|
|
103
|
-
expire_index!
|
|
104
|
-
super
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def append_path(path)
|
|
108
|
-
# Overrides the global behavior to expire the index
|
|
109
|
-
expire_index!
|
|
110
|
-
super
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def clear_paths
|
|
114
|
-
# Overrides the global behavior to expire the index
|
|
115
|
-
expire_index!
|
|
116
|
-
super
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# Finds the expanded real path for a given logical path by
|
|
120
|
-
# searching the environment's paths.
|
|
121
|
-
#
|
|
122
|
-
# resolve("application.js")
|
|
123
|
-
# # => "/path/to/app/javascripts/application.js.coffee"
|
|
124
|
-
#
|
|
125
|
-
# A `FileNotFound` exception is raised if the file does not exist.
|
|
126
|
-
def resolve(logical_path, options = {})
|
|
127
|
-
# If a block is given, preform an iterable search
|
|
128
|
-
if block_given?
|
|
129
|
-
args = attributes_for(logical_path).search_paths + [options]
|
|
130
|
-
@trail.find(*args) do |path|
|
|
131
|
-
pathname = Pathname.new(path)
|
|
132
|
-
if pathname.basename.to_s == 'component.json'
|
|
133
|
-
component = json_decode(pathname.read)
|
|
134
|
-
case component['main']
|
|
135
|
-
when String
|
|
136
|
-
yield pathname.dirname.join(component['main'])
|
|
137
|
-
when Array
|
|
138
|
-
extname = File.extname(logical_path)
|
|
139
|
-
component['main'].each do |fn|
|
|
140
|
-
if extname == "" || extname == File.extname(fn)
|
|
141
|
-
yield pathname.dirname.join(fn)
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
else
|
|
146
|
-
yield pathname
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
else
|
|
150
|
-
resolve(logical_path, options) do |pathname|
|
|
151
|
-
return pathname
|
|
152
|
-
end
|
|
153
|
-
raise FileNotFound, "couldn't find file '#{logical_path}'"
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
# Register a new mime type.
|
|
158
|
-
def register_mime_type(mime_type, ext)
|
|
159
|
-
# Overrides the global behavior to expire the index
|
|
160
|
-
expire_index!
|
|
161
|
-
@trail.append_extension(ext)
|
|
162
|
-
super
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
# Registers a new Engine `klass` for `ext`.
|
|
166
|
-
def register_engine(ext, klass)
|
|
167
|
-
# Overrides the global behavior to expire the index
|
|
168
|
-
expire_index!
|
|
169
|
-
add_engine_to_trail(ext, klass)
|
|
170
|
-
super
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
def register_preprocessor(mime_type, klass, &block)
|
|
174
|
-
# Overrides the global behavior to expire the index
|
|
175
|
-
expire_index!
|
|
176
|
-
super
|
|
49
|
+
@cache = Cache.new(cache, logger)
|
|
177
50
|
end
|
|
178
51
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
expire_index!
|
|
182
|
-
super
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
def register_postprocessor(mime_type, klass, &block)
|
|
186
|
-
# Overrides the global behavior to expire the index
|
|
187
|
-
expire_index!
|
|
188
|
-
super
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
def unregister_postprocessor(mime_type, klass)
|
|
192
|
-
# Overrides the global behavior to expire the index
|
|
193
|
-
expire_index!
|
|
194
|
-
super
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
def register_bundle_processor(mime_type, klass, &block)
|
|
198
|
-
# Overrides the global behavior to expire the index
|
|
199
|
-
expire_index!
|
|
200
|
-
super
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
def unregister_bundle_processor(mime_type, klass)
|
|
204
|
-
# Overrides the global behavior to expire the index
|
|
205
|
-
expire_index!
|
|
206
|
-
super
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
# Return an `Index`. Must be implemented by the subclass.
|
|
210
|
-
def index
|
|
52
|
+
# Return an `CachedEnvironment`. Must be implemented by the subclass.
|
|
53
|
+
def cached
|
|
211
54
|
raise NotImplementedError
|
|
212
55
|
end
|
|
56
|
+
alias_method :index, :cached
|
|
213
57
|
|
|
214
|
-
|
|
215
|
-
# Define `default_external_encoding` accessor on 1.9.
|
|
216
|
-
# Defaults to UTF-8.
|
|
217
|
-
attr_accessor :default_external_encoding
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
# Works like `Dir.entries`.
|
|
221
|
-
#
|
|
222
|
-
# Subclasses may cache this method.
|
|
223
|
-
def entries(pathname)
|
|
224
|
-
@trail.entries(pathname)
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
# Works like `File.stat`.
|
|
58
|
+
# Internal: Compute digest for path.
|
|
228
59
|
#
|
|
229
|
-
#
|
|
230
|
-
def stat(path)
|
|
231
|
-
@trail.stat(path)
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
# Read and compute digest of filename.
|
|
60
|
+
# path - String filename or directory path.
|
|
235
61
|
#
|
|
236
|
-
#
|
|
62
|
+
# Returns a String digest or nil.
|
|
237
63
|
def file_digest(path)
|
|
238
64
|
if stat = self.stat(path)
|
|
239
|
-
#
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
#
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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)
|
|
247
73
|
end
|
|
248
74
|
end
|
|
249
75
|
end
|
|
250
76
|
|
|
251
|
-
#
|
|
252
|
-
def
|
|
253
|
-
|
|
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
|
|
254
83
|
end
|
|
255
84
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
attributes_for(path).content_type
|
|
259
|
-
end
|
|
85
|
+
def find_all_linked_assets(*args)
|
|
86
|
+
return to_enum(__method__, *args) unless block_given?
|
|
260
87
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
logical_path = path
|
|
264
|
-
pathname = Pathname.new(path)
|
|
88
|
+
parent_asset = asset = find_asset(*args)
|
|
89
|
+
return unless asset
|
|
265
90
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
else
|
|
270
|
-
begin
|
|
271
|
-
pathname = resolve(logical_path)
|
|
91
|
+
yield asset
|
|
92
|
+
stack = asset.links.to_a
|
|
93
|
+
linked_paths = {}
|
|
272
94
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
95
|
+
while uri = stack.shift
|
|
96
|
+
yield asset = load(uri)
|
|
97
|
+
|
|
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
|
+
)
|
|
284
106
|
end
|
|
107
|
+
linked_paths[asset.logical_path] = asset.filename
|
|
108
|
+
stack = asset.links.to_a + stack
|
|
285
109
|
end
|
|
286
110
|
|
|
287
|
-
|
|
111
|
+
nil
|
|
288
112
|
end
|
|
289
113
|
|
|
290
114
|
# Preferred `find_asset` shorthand.
|
|
291
115
|
#
|
|
292
116
|
# environment['application.js']
|
|
293
117
|
#
|
|
294
|
-
def [](*args)
|
|
295
|
-
find_asset(*args)
|
|
296
|
-
end
|
|
297
|
-
|
|
298
|
-
def each_entry(root, &block)
|
|
299
|
-
return to_enum(__method__, root) unless block_given?
|
|
300
|
-
root = Pathname.new(root) unless root.is_a?(Pathname)
|
|
301
|
-
|
|
302
|
-
paths = []
|
|
303
|
-
entries(root).sort.each do |filename|
|
|
304
|
-
path = root.join(filename)
|
|
305
|
-
paths << path
|
|
306
|
-
|
|
307
|
-
if stat(path).directory?
|
|
308
|
-
each_entry(path) do |subpath|
|
|
309
|
-
paths << subpath
|
|
310
|
-
end
|
|
311
|
-
end
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
paths.sort_by(&:to_s).each(&block)
|
|
315
|
-
|
|
316
|
-
nil
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
def each_file
|
|
320
|
-
return to_enum(__method__) unless block_given?
|
|
321
|
-
paths.each do |root|
|
|
322
|
-
each_entry(root) do |path|
|
|
323
|
-
if !stat(path).directory?
|
|
324
|
-
yield path
|
|
325
|
-
end
|
|
326
|
-
end
|
|
327
|
-
end
|
|
328
|
-
nil
|
|
118
|
+
def [](*args, **options)
|
|
119
|
+
find_asset(*args, **options)
|
|
329
120
|
end
|
|
330
121
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
files[logical_path] = true
|
|
339
|
-
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)
|
|
340
129
|
end
|
|
341
|
-
nil
|
|
342
130
|
end
|
|
343
131
|
|
|
344
132
|
# Pretty inspect
|
|
345
133
|
def inspect
|
|
346
134
|
"#<#{self.class}:0x#{object_id.to_s(16)} " +
|
|
347
135
|
"root=#{root.to_s.inspect}, " +
|
|
348
|
-
"paths=#{paths.inspect}
|
|
349
|
-
"digest=#{digest.to_s.inspect}" +
|
|
350
|
-
">"
|
|
136
|
+
"paths=#{paths.inspect}>"
|
|
351
137
|
end
|
|
352
138
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
raise NotImplementedError
|
|
357
|
-
end
|
|
358
|
-
|
|
359
|
-
def build_asset(logical_path, pathname, options)
|
|
360
|
-
pathname = Pathname.new(pathname)
|
|
361
|
-
|
|
362
|
-
# If there are any processors to run on the pathname, use
|
|
363
|
-
# `BundledAsset`. Otherwise use `StaticAsset` and treat is as binary.
|
|
364
|
-
if attributes_for(pathname).processors.any?
|
|
365
|
-
if options[:bundle] == false
|
|
366
|
-
circular_call_protection(pathname.to_s) do
|
|
367
|
-
ProcessedAsset.new(index, logical_path, pathname)
|
|
368
|
-
end
|
|
369
|
-
else
|
|
370
|
-
BundledAsset.new(index, logical_path, pathname)
|
|
371
|
-
end
|
|
372
|
-
else
|
|
373
|
-
StaticAsset.new(index, logical_path, pathname)
|
|
374
|
-
end
|
|
375
|
-
end
|
|
376
|
-
|
|
377
|
-
def cache_key_for(path, options)
|
|
378
|
-
"#{path}:#{options[:bundle] ? '1' : '0'}"
|
|
379
|
-
end
|
|
380
|
-
|
|
381
|
-
def circular_call_protection(path)
|
|
382
|
-
reset = Thread.current[:sprockets_circular_calls].nil?
|
|
383
|
-
calls = Thread.current[:sprockets_circular_calls] ||= Set.new
|
|
384
|
-
if calls.include?(path)
|
|
385
|
-
raise CircularDependencyError, "#{path} has already been required"
|
|
386
|
-
end
|
|
387
|
-
calls << path
|
|
388
|
-
yield
|
|
389
|
-
ensure
|
|
390
|
-
Thread.current[:sprockets_circular_calls] = nil if reset
|
|
391
|
-
end
|
|
392
|
-
|
|
393
|
-
def logical_path_for_filename(filename, filters)
|
|
394
|
-
logical_path = attributes_for(filename).logical_path.to_s
|
|
395
|
-
|
|
396
|
-
if matches_filter(filters, logical_path)
|
|
397
|
-
return logical_path
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
# If filename is an index file, retest with alias
|
|
401
|
-
if File.basename(logical_path)[/[^\.]+/, 0] == 'index'
|
|
402
|
-
path = logical_path.sub(/\/index\./, '.')
|
|
403
|
-
if matches_filter(filters, path)
|
|
404
|
-
return path
|
|
405
|
-
end
|
|
406
|
-
end
|
|
407
|
-
|
|
408
|
-
nil
|
|
409
|
-
end
|
|
410
|
-
|
|
411
|
-
def matches_filter(filters, filename)
|
|
412
|
-
return true if filters.empty?
|
|
413
|
-
|
|
414
|
-
filters.any? do |filter|
|
|
415
|
-
if filter.is_a?(Regexp)
|
|
416
|
-
filter.match(filename)
|
|
417
|
-
elsif filter.respond_to?(:call)
|
|
418
|
-
filter.call(filename)
|
|
419
|
-
else
|
|
420
|
-
File.fnmatch(filter.to_s, filename)
|
|
421
|
-
end
|
|
422
|
-
end
|
|
423
|
-
end
|
|
139
|
+
def compress_from_root(uri)
|
|
140
|
+
URITar.new(uri, self).compress
|
|
141
|
+
end
|
|
424
142
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
MultiJson.load(obj)
|
|
429
|
-
end
|
|
430
|
-
else
|
|
431
|
-
def json_decode(obj)
|
|
432
|
-
MultiJson.decode(obj)
|
|
433
|
-
end
|
|
434
|
-
end
|
|
143
|
+
def expand_from_root(uri)
|
|
144
|
+
URITar.new(uri, self).expand
|
|
145
|
+
end
|
|
435
146
|
end
|
|
436
147
|
end
|