darkroom 0.0.8 → 0.0.10
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 +92 -0
- data/LICENSE +1 -1
- data/README.md +430 -114
- data/VERSION +1 -1
- data/lib/darkroom/asset.rb +176 -164
- data/lib/darkroom/darkroom.rb +140 -149
- data/lib/darkroom/delegate.rb +204 -161
- data/lib/darkroom/delegates/{css.rb → css_delegate.rb} +1 -0
- data/lib/darkroom/delegates/{html.rb → html_delegate.rb} +4 -3
- data/lib/darkroom/delegates/{htx.rb → htx_delegate.rb} +3 -2
- data/lib/darkroom/delegates/{javascript.rb → javascript_delegate.rb} +9 -8
- data/lib/darkroom/errors/asset_error.rb +6 -17
- data/lib/darkroom/errors/asset_not_found_error.rb +4 -8
- data/lib/darkroom/errors/circular_reference_error.rb +4 -8
- data/lib/darkroom/errors/duplicate_asset_error.rb +7 -16
- data/lib/darkroom/errors/invalid_path_error.rb +5 -14
- data/lib/darkroom/errors/missing_library_error.rb +7 -16
- data/lib/darkroom/errors/processing_error.rb +13 -20
- data/lib/darkroom/errors/unrecognized_extension_error.rb +4 -8
- data/lib/darkroom/version.rb +1 -1
- data/lib/darkroom.rb +8 -6
- metadata +36 -30
data/lib/darkroom/darkroom.rb
CHANGED
@@ -3,17 +3,16 @@
|
|
3
3
|
require('set')
|
4
4
|
|
5
5
|
require_relative('asset')
|
6
|
+
require_relative('delegate')
|
6
7
|
require_relative('errors/asset_not_found_error')
|
7
8
|
require_relative('errors/duplicate_asset_error')
|
8
9
|
require_relative('errors/invalid_path_error')
|
9
10
|
require_relative('errors/processing_error')
|
10
11
|
|
11
|
-
|
12
|
-
# Main class providing fast, lightweight, and straightforward web asset management.
|
13
|
-
#
|
12
|
+
# Main class providing simple and straightforward web asset management.
|
14
13
|
class Darkroom
|
15
14
|
DEFAULT_MINIFIED = /(\.|-)min\.\w+$/.freeze
|
16
|
-
TRAILING_SLASHES =
|
15
|
+
TRAILING_SLASHES = %r{/+$}.freeze
|
17
16
|
PRISTINE = Set.new(%w[/favicon.ico /mask-icon.svg /humans.txt /robots.txt]).freeze
|
18
17
|
MIN_PROCESS_INTERVAL = 0.5
|
19
18
|
|
@@ -24,29 +23,36 @@ class Darkroom
|
|
24
23
|
|
25
24
|
class << self; attr_accessor(:javascript_iife) end
|
26
25
|
|
27
|
-
|
28
|
-
# Registers an asset delegate.
|
26
|
+
# Public: Register a delegate for handling a specific kind of asset.
|
29
27
|
#
|
30
|
-
#
|
31
|
-
#
|
28
|
+
# args - One or more String file extensions to associate with this delegate, optionally followed by
|
29
|
+
# either an HTTP MIME type String or a Delegate subclass.
|
30
|
+
# block - Block to call that defines or extends the Delegate.
|
32
31
|
#
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
32
|
+
# Examples
|
33
|
+
#
|
34
|
+
# Darkroom.register('.ext1', '.ext2', 'content/type')
|
35
|
+
# Darkroom.register('.ext', MyDelegateSubclass)
|
36
|
+
#
|
37
|
+
# Darkroom.register('.scss', 'text/css') do
|
38
|
+
# compile(lib: 'sassc') { ... }
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# Darkroom.register('.scss', SCSSDelegate) do
|
42
|
+
# # Modifications/overrides of the SCSSDelegate class...
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# Returns the Delegate class.
|
46
|
+
def self.register(*args, &block)
|
47
|
+
last_arg = args.pop unless args.last.kind_of?(String) && args.last[0] == '.'
|
48
|
+
extensions = args
|
41
49
|
|
50
|
+
if last_arg.nil? || last_arg.kind_of?(String)
|
51
|
+
content_type = last_arg
|
42
52
|
delegate = Class.new(Delegate, &block)
|
43
53
|
delegate.content_type(content_type) if content_type && !delegate.content_type
|
44
|
-
elsif
|
45
|
-
|
46
|
-
'instead')
|
47
|
-
delegate = Delegate.deprecated_from_hash(**delegate)
|
48
|
-
elsif delegate && delegate < Delegate
|
49
|
-
delegate = block ? Class.new(delegate, &block) : delegate
|
54
|
+
elsif last_arg.kind_of?(Class) && last_arg < Delegate
|
55
|
+
delegate = block ? Class.new(last_arg, &block) : last_arg
|
50
56
|
end
|
51
57
|
|
52
58
|
extensions.each do |extension|
|
@@ -58,66 +64,41 @@ class Darkroom
|
|
58
64
|
delegate
|
59
65
|
end
|
60
66
|
|
61
|
-
|
62
|
-
# Returns the delegate associated with a file extension.
|
67
|
+
# Public: Get the Delegate associated with a file extension.
|
63
68
|
#
|
64
|
-
#
|
69
|
+
# extension - String file extension of the desired delegate (e.g. '.js')
|
65
70
|
#
|
71
|
+
# Returns the Delegate class.
|
66
72
|
def self.delegate(extension)
|
67
73
|
@@delegates[extension]
|
68
74
|
end
|
69
75
|
|
70
|
-
|
71
|
-
# Utility method that prints a warning with file and line number of a deprecated call.
|
72
|
-
#
|
73
|
-
def self.deprecated(message)
|
74
|
-
location = caller_locations(2, 1).first
|
75
|
-
|
76
|
-
warn("#{location.path}:#{location.lineno}: #{message}")
|
77
|
-
end
|
78
|
-
|
79
|
-
##
|
80
|
-
# Creates a new instance.
|
81
|
-
#
|
82
|
-
# [*load_paths] One or more paths where assets are located on disk.
|
83
|
-
# [host:] Host(s) to prepend to paths (useful when serving from a CDN in production). If multiple hosts
|
84
|
-
# are specified, they will be round-robined within each thread for each call to +#asset_path+.
|
85
|
-
# [hosts:] Alias of +host:+.
|
86
|
-
# [prefix:] Prefix to prepend to asset paths (e.g. +/assets+).
|
87
|
-
# [pristine:] Path(s) that should not include prefix and for which unversioned form should be provided by
|
88
|
-
# default (e.g. +/favicon.ico+).
|
89
|
-
# [entries:] String, regex, or array of strings and regexes specifying entry point paths / path patterns.
|
90
|
-
# [minify:] Boolean specifying whether or not to minify assets.
|
91
|
-
# [minified:] String, regex, or array of strings and regexes specifying paths of assets that are already
|
92
|
-
# minified and thus should be skipped for minification.
|
93
|
-
# [minified_pattern:] DEPRECATED: use +minified:+ instead. Regex used against asset paths to determine if
|
94
|
-
# they are already minified and should therefore be skipped over for minification.
|
95
|
-
# [internal_pattern:] DEPRECATED: use +entries:+ instead. Regex used against asset paths to determine if
|
96
|
-
# they should be marked as internal and therefore made inaccessible externally.
|
97
|
-
# [min_process_interval:] Minimum time required between one run of asset processing and another.
|
76
|
+
# Public: Create a new instance.
|
98
77
|
#
|
78
|
+
# load_paths - One or more String paths where assets are located on disk.
|
79
|
+
# host: - String host or Array of String hosts to prepend to paths (useful when serving
|
80
|
+
# from a CDN in production). If multiple hosts are specified, they will be round-
|
81
|
+
# robined within each thread for each call to #asset_path.
|
82
|
+
# hosts: - String or Array of Strings (alias of host:).
|
83
|
+
# prefix: - String prefix to prepend to asset paths (e.g. '/assets').
|
84
|
+
# pristine: - String, Array of String, or Set of String paths that should not include the
|
85
|
+
# prefix and for which the unversioned form should be provided by default (e.g.
|
86
|
+
# '/favicon.ico').
|
87
|
+
# entries: - String, Regexp, or Array of String and/or Regexp specifying entry point paths /
|
88
|
+
# path patterns.
|
89
|
+
# minify: - Boolean specifying if assets that support it should be minified.
|
90
|
+
# minified: - String, Regexp, or Array of String and/or Regexp specifying paths of assets that
|
91
|
+
# are already minified and thus shouldn't be minified.
|
92
|
+
# min_process_interval: - Numeric minimum number of seconds required between one run of asset processing
|
93
|
+
# and another.
|
99
94
|
def initialize(*load_paths, host: nil, hosts: nil, prefix: nil, pristine: nil, entries: nil,
|
100
|
-
|
101
|
-
min_process_interval: MIN_PROCESS_INTERVAL)
|
95
|
+
minify: false, minified: DEFAULT_MINIFIED, min_process_interval: MIN_PROCESS_INTERVAL)
|
102
96
|
@load_paths = load_paths.map { |load_path| File.expand_path(load_path) }
|
103
97
|
|
104
|
-
@hosts = (Array(host) + Array(hosts)).map! { |
|
98
|
+
@hosts = (Array(host) + Array(hosts)).map! { |h| h.sub(TRAILING_SLASHES, '') }
|
105
99
|
@entries = Array(entries)
|
106
100
|
@minify = minify
|
107
101
|
@minified = Array(minified)
|
108
|
-
@internal_pattern = internal_pattern
|
109
|
-
|
110
|
-
if minified_pattern
|
111
|
-
self.class.deprecated("#{self.class.name} :minified_pattern is deprecated: use :minified instead "\
|
112
|
-
'and pass a string, regex, or array of strings and regexes')
|
113
|
-
@minified = [minified_pattern]
|
114
|
-
end
|
115
|
-
|
116
|
-
if @internal_pattern
|
117
|
-
self.class.deprecated("#{self.class.name} :internal_pattern is deprecated: use :entries to instead "\
|
118
|
-
'specify which assets are entry points (i.e. available externally) and pass a string, regex, or '\
|
119
|
-
'array of strings and regexes')
|
120
|
-
end
|
121
102
|
|
122
103
|
@prefix = prefix&.sub(TRAILING_SLASHES, '')
|
123
104
|
@prefix = nil if @prefix && @prefix.empty?
|
@@ -138,16 +119,24 @@ class Darkroom
|
|
138
119
|
Thread.current[:darkroom_host_index] = -1 unless @hosts.empty?
|
139
120
|
end
|
140
121
|
|
141
|
-
|
142
|
-
#
|
143
|
-
#
|
144
|
-
#
|
122
|
+
# Public: Walk all load paths and refresh any assets that have been modified on disk since the last call
|
123
|
+
# to this method. Processing is skipped if either a) a previous call to this method happened
|
124
|
+
# less than min_process_interval seconds ago or b) another thread is currently executing this method.
|
125
|
+
#
|
126
|
+
# A mutex is used to ensure that, say, multiple web request threads do not trample each other. If the
|
127
|
+
# mutex is locked when this method is called, it will wait until the mutex is released to ensure that the
|
128
|
+
# caller does not then start working with stale / invalid Asset objects due to the work of the other
|
129
|
+
# thread's active call to #process being incomplete.
|
130
|
+
#
|
131
|
+
# If any errors are encountered during processing, they must be checked for manually afterward via #error
|
132
|
+
# or #errors. If a raise is preferred, use #process! instead.
|
145
133
|
#
|
134
|
+
# Returns boolean indicating if processing actually happened (true) or was skipped (false).
|
146
135
|
def process
|
147
136
|
return false if Time.now.to_f - @last_processed_at < @min_process_interval
|
148
137
|
|
149
138
|
if @mutex.locked?
|
150
|
-
@mutex.synchronize {}
|
139
|
+
@mutex.synchronize {} # Wait until other #process call is done to avoid stale/invalid assets.
|
151
140
|
return false
|
152
141
|
end
|
153
142
|
|
@@ -157,10 +146,10 @@ class Darkroom
|
|
157
146
|
found = {}
|
158
147
|
|
159
148
|
@load_paths.each do |load_path|
|
160
|
-
Dir.glob(File.join(load_path, @@glob)).
|
149
|
+
Dir.glob(File.join(load_path, @@glob)).each do |file|
|
161
150
|
path = file.sub(load_path, '')
|
162
151
|
|
163
|
-
if index = (
|
152
|
+
if (index = path.index(Asset::INVALID_PATH_REGEX))
|
164
153
|
@errors << InvalidPathError.new(path, index)
|
165
154
|
elsif found.key?(path)
|
166
155
|
@errors << DuplicateAssetError.new(path, found[path], load_path)
|
@@ -170,7 +159,8 @@ class Darkroom
|
|
170
159
|
unless @manifest.key?(path)
|
171
160
|
entry = entry?(path)
|
172
161
|
|
173
|
-
@manifest[path] = Asset.new(
|
162
|
+
@manifest[path] = Asset.new(
|
163
|
+
path, file, self,
|
174
164
|
prefix: (@prefix unless @pristine.include?(path)),
|
175
165
|
entry: entry,
|
176
166
|
minify: entry && @minify && !minified?(path),
|
@@ -184,7 +174,7 @@ class Darkroom
|
|
184
174
|
@manifest_unversioned.clear
|
185
175
|
@manifest_versioned.clear
|
186
176
|
|
187
|
-
@manifest.
|
177
|
+
@manifest.each_value do |asset|
|
188
178
|
asset.process
|
189
179
|
|
190
180
|
if asset.entry?
|
@@ -202,94 +192,102 @@ class Darkroom
|
|
202
192
|
end
|
203
193
|
end
|
204
194
|
|
205
|
-
|
206
|
-
# Calls #process. If processing was skipped, returns false. If processing was performed, raises an
|
207
|
-
# exception if any errors were encountered and returns true otherwise.
|
195
|
+
# Public: Call #process but raise an error if there were errors.
|
208
196
|
#
|
197
|
+
# Returns boolean indicating if processing actually happened (true) or was skipped (false).
|
198
|
+
# Raises ProcessingError if processing actually happened from this call and error(s) were encountered.
|
209
199
|
def process!
|
210
200
|
result = process
|
211
201
|
|
212
|
-
|
202
|
+
result && @error ? raise(@error) : result
|
213
203
|
end
|
214
204
|
|
215
|
-
|
216
|
-
# Returns boolean indicating whether or not there were any errors encountered the last time assets were
|
217
|
-
# processed.
|
205
|
+
# Public: Check if there were any errors encountered the last time assets were processed.
|
218
206
|
#
|
207
|
+
# Returns the boolean result.
|
219
208
|
def error?
|
220
209
|
!!@error
|
221
210
|
end
|
222
211
|
|
223
|
-
|
224
|
-
#
|
225
|
-
# either the versioned or unversioned form of the asset path (i.e. how an HTTP request for the asset comes
|
226
|
-
# in). For example, to get the Asset object with path +/js/app.js+ when prefix is +/assets+:
|
212
|
+
# Public: Get an Asset object, given its external path. An external path includes any prefix and can be
|
213
|
+
# either the versioned or unversioned form (i.e. how an HTTP request for the asset comes in).
|
227
214
|
#
|
228
|
-
#
|
229
|
-
# darkroom.asset('/assets/js/app.js')
|
215
|
+
# Examples
|
230
216
|
#
|
231
|
-
#
|
217
|
+
# # Suppose the asset's internal path is '/js/app.js' and the prefix is '/assets'.
|
218
|
+
# darkroom.asset('/assets/js/app-<hash>.js') # => #<Darkroom::Asset [...]>
|
219
|
+
# darkroom.asset('/assets/js/app.js') # => #<Darkroom::Asset [...]>
|
232
220
|
#
|
221
|
+
# path - String external path of the asset.
|
222
|
+
#
|
223
|
+
# Returns the Asset object if it exists or nil otherwise.
|
233
224
|
def asset(path)
|
234
225
|
@manifest_versioned[path] || @manifest_unversioned[path]
|
235
226
|
end
|
236
227
|
|
237
|
-
|
238
|
-
#
|
239
|
-
# can be either the versioned or unversioned form of the asset path (i.e. how an HTTP request for the
|
240
|
-
# asset comes in). For example, to get the external path for the Asset object with path +/js/app.js+ when
|
241
|
-
# prefix is +/assets+:
|
228
|
+
# Public: Get the external asset path, given its internal path. An external path includes any prefix and
|
229
|
+
# can be either the versioned or unversioned form (i.e. how an HTTP request for the asset comes in).
|
242
230
|
#
|
243
|
-
#
|
244
|
-
#
|
231
|
+
# path - String internal path of the asset.
|
232
|
+
# versioned: - Boolean specifying either the versioned or unversioned path to be returned.
|
245
233
|
#
|
246
|
-
#
|
234
|
+
# Examples
|
247
235
|
#
|
248
|
-
#
|
249
|
-
#
|
236
|
+
# # Suppose the asset's internal path is '/js/app.js' and the prefix is '/assets'.
|
237
|
+
# darkroom.asset_path('/js/app.js') # => "/assets/js/app-<hash>.js"
|
238
|
+
# darkroom.asset_path('/js/app.js', versioned: false) # => "/assets/js/app.js"
|
250
239
|
#
|
240
|
+
# Returns the String external asset path.
|
241
|
+
# Raises AssetNotFoundError if the asset doesn't exist.
|
251
242
|
def asset_path(path, versioned: !@pristine.include?(path))
|
252
243
|
asset = @manifest[path] or raise(AssetNotFoundError.new(path))
|
253
|
-
|
254
|
-
|
255
|
-
|
244
|
+
|
245
|
+
unless @hosts.empty?
|
246
|
+
host_index = (Thread.current[:darkroom_host_index] + 1) % @hosts.size
|
247
|
+
host = @hosts[host_index]
|
248
|
+
|
249
|
+
Thread.current[:darkroom_host_index] = host_index
|
250
|
+
end
|
256
251
|
|
257
252
|
"#{host}#{versioned ? asset.path_versioned : asset.path_unversioned}"
|
258
253
|
end
|
259
254
|
|
260
|
-
|
261
|
-
# Returns an asset's subresource integrity string. Raises an AssetNotFoundError if the asset doesn't
|
262
|
-
# exist.
|
255
|
+
# Public: Get an asset's subresource integrity string.
|
263
256
|
#
|
264
|
-
#
|
265
|
-
#
|
257
|
+
# path - String internal path of the asset.
|
258
|
+
# algorithm - Symbol hash algorithm name to use to generate the integrity string (must be one of
|
259
|
+
# :sha256, :sha384, :sha512).
|
266
260
|
#
|
261
|
+
# Returns the asset's subresource integrity String.
|
262
|
+
# Raises AssetNotFoundError if the asset doesn't exist.
|
267
263
|
def asset_integrity(path, algorithm = nil)
|
268
264
|
asset = @manifest[path] or raise(AssetNotFoundError.new(path))
|
269
265
|
|
270
266
|
algorithm ? asset.integrity(algorithm) : asset.integrity
|
271
267
|
end
|
272
268
|
|
273
|
-
|
274
|
-
# Returns the asset from the manifest hash associated with the given path.
|
269
|
+
# Public: Get the Asset object from the manifest Hash associated with the given path.
|
275
270
|
#
|
276
|
-
#
|
271
|
+
# path - String internal path of the asset.
|
277
272
|
#
|
273
|
+
# Returns the Asset object if it exists or nil otherwise.
|
278
274
|
def manifest(path)
|
279
275
|
@manifest[path]
|
280
276
|
end
|
281
277
|
|
282
|
-
|
283
|
-
#
|
284
|
-
#
|
278
|
+
# Public: Write assets to disk. This is useful when deploying to a production environment where assets
|
279
|
+
# will be uploaded to and served from a CDN or proxy server. Note that #process must be called manually
|
280
|
+
# before calling this method.
|
285
281
|
#
|
286
|
-
#
|
287
|
-
#
|
288
|
-
#
|
289
|
-
#
|
282
|
+
# dir - String directory path to write the assets to.
|
283
|
+
# clear: - Boolean indicating if the existing contents of the directory should be deleted
|
284
|
+
# before writing files.
|
285
|
+
# include_pristine: - Boolean indicating if pristine assets should be included (when dumping for the
|
290
286
|
# purpose of uploading to a CDN, assets such as /robots.txt and /favicon.ico don't
|
291
287
|
# need to be included).
|
292
288
|
#
|
289
|
+
# Returns nothing.
|
290
|
+
# Raises ProcessingError if errors were encountered during the last #process run.
|
293
291
|
def dump(dir, clear: false, include_pristine: true)
|
294
292
|
raise(@error) if @error
|
295
293
|
|
@@ -303,48 +301,41 @@ class Darkroom
|
|
303
301
|
@manifest_versioned.each do |path, asset|
|
304
302
|
next if @pristine.include?(asset.path) && !include_pristine
|
305
303
|
|
306
|
-
file_path = File.join(dir,
|
307
|
-
@pristine.include?(asset.path) ? asset.path_unversioned : path
|
308
|
-
)
|
304
|
+
file_path = File.join(dir, @pristine.include?(asset.path) ? asset.path_unversioned : path)
|
309
305
|
|
310
306
|
FileUtils.mkdir_p(File.dirname(file_path))
|
311
307
|
File.write(file_path, asset.content)
|
312
308
|
end
|
313
309
|
end
|
314
310
|
|
315
|
-
|
316
|
-
# Returns high-level object info string.
|
311
|
+
# Public: Get a high-level object info string about this Darkroom instance.
|
317
312
|
#
|
313
|
+
# Returns the String.
|
318
314
|
def inspect
|
319
|
-
"#<#{self.class}
|
320
|
-
"@entries=#{@entries.inspect}, "\
|
321
|
-
"@errors=#{@errors.inspect}, "\
|
322
|
-
"@hosts=#{@hosts.inspect}, "\
|
323
|
-
"@
|
324
|
-
"@
|
325
|
-
"@
|
326
|
-
"@
|
327
|
-
"@
|
328
|
-
"@
|
329
|
-
"@
|
330
|
-
"@
|
331
|
-
"@process_key=#{@process_key.inspect}"\
|
315
|
+
"#<#{self.class} " \
|
316
|
+
"@entries=#{@entries.inspect}, " \
|
317
|
+
"@errors=#{@errors.inspect}, " \
|
318
|
+
"@hosts=#{@hosts.inspect}, " \
|
319
|
+
"@last_processed_at=#{@last_processed_at.inspect}, " \
|
320
|
+
"@load_paths=#{@load_paths.inspect}, " \
|
321
|
+
"@min_process_interval=#{@min_process_interval.inspect}, " \
|
322
|
+
"@minified=#{@minified.inspect}, " \
|
323
|
+
"@minify=#{@minify.inspect}, " \
|
324
|
+
"@prefix=#{@prefix.inspect}, " \
|
325
|
+
"@pristine=#{@pristine.inspect}, " \
|
326
|
+
"@process_key=#{@process_key.inspect}" \
|
332
327
|
'>'
|
333
328
|
end
|
334
329
|
|
335
330
|
private
|
336
331
|
|
337
|
-
|
338
|
-
# Returns boolean indicating whether or not the provided path is an entry point.
|
332
|
+
# Internal: Check if an asset's path indicates that it's an entry point.
|
339
333
|
#
|
340
|
-
#
|
334
|
+
# path - String asset path to check.
|
341
335
|
#
|
336
|
+
# Returns the boolean result.
|
342
337
|
def entry?(path)
|
343
|
-
if @pristine.include?(path)
|
344
|
-
true
|
345
|
-
elsif @internal_pattern && @entries.empty?
|
346
|
-
!path.match?(@internal_pattern)
|
347
|
-
elsif @entries.empty?
|
338
|
+
if @pristine.include?(path) || @entries.empty?
|
348
339
|
true
|
349
340
|
else
|
350
341
|
@entries.any? do |entry|
|
@@ -353,11 +344,11 @@ class Darkroom
|
|
353
344
|
end
|
354
345
|
end
|
355
346
|
|
356
|
-
|
357
|
-
# Returns boolean indicating whether or not the asset with the provided path is already minified.
|
347
|
+
# Internal: Check if an asset's path indicates that it's already minified.
|
358
348
|
#
|
359
|
-
#
|
349
|
+
# path - String asset path to check.
|
360
350
|
#
|
351
|
+
# Returns the boolean result.
|
361
352
|
def minified?(path)
|
362
353
|
@minified.any? do |minified|
|
363
354
|
path == minified || (minified.kind_of?(Regexp) && path.match?(minified))
|