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/asset.rb
CHANGED
@@ -4,6 +4,7 @@ require('base64')
|
|
4
4
|
require('digest')
|
5
5
|
require('set')
|
6
6
|
|
7
|
+
require_relative('delegate')
|
7
8
|
require_relative('errors/asset_error')
|
8
9
|
require_relative('errors/asset_not_found_error')
|
9
10
|
require_relative('errors/circular_reference_error')
|
@@ -12,9 +13,7 @@ require_relative('errors/processing_error')
|
|
12
13
|
require_relative('errors/unrecognized_extension_error')
|
13
14
|
|
14
15
|
class Darkroom
|
15
|
-
##
|
16
16
|
# Represents an asset.
|
17
|
-
#
|
18
17
|
class Asset
|
19
18
|
EXTENSION_REGEX = /(?=\.\w+)/.freeze
|
20
19
|
DEFAULT_QUOTE = '\''
|
@@ -28,6 +27,8 @@ class Darkroom
|
|
28
27
|
\k<quote>
|
29
28
|
/x.freeze
|
30
29
|
|
30
|
+
BUILT_IN_PARSE_KINDS = [:import, :reference].freeze
|
31
|
+
|
31
32
|
# First item of each set is used as default, so order is important.
|
32
33
|
REFERENCE_FORMATS = {
|
33
34
|
'path' => Set.new(%w[versioned unversioned]),
|
@@ -36,18 +37,16 @@ class Darkroom
|
|
36
37
|
|
37
38
|
attr_reader(:errors, :path, :path_unversioned)
|
38
39
|
|
39
|
-
|
40
|
-
# Creates a new instance.
|
41
|
-
#
|
42
|
-
# [file] Path of file on disk.
|
43
|
-
# [path] Path this asset will be referenced by (e.g. /js/app.js).
|
44
|
-
# [darkroom] Darkroom instance that the asset is a member of.
|
45
|
-
# [prefix:] Prefix to apply to unversioned and versioned paths.
|
46
|
-
# [entry:] Boolean indicating whether or not the asset is an entry point (i.e. accessible externally).
|
47
|
-
# [minify:] Boolean specifying whether or not the asset should be minified when processed.
|
48
|
-
# [intermediate:] Boolean indicating whether or not the asset exists solely to provide an intermediate
|
49
|
-
# form (e.g. compiled) to another asset instance.
|
40
|
+
# Public: Create a new instance.
|
50
41
|
#
|
42
|
+
# path - String path this asset will be referenced by (e.g. /js/app.js).
|
43
|
+
# file - String absolute path of file on disk.
|
44
|
+
# darkroom - Darkroom instance that the asset is a member of.
|
45
|
+
# prefix: - String prefix to apply to unversioned and versioned paths.
|
46
|
+
# entry: - Boolean specifying if the asset is an entry point (i.e. accessible externally).
|
47
|
+
# minify: - Boolean specifying if the asset should be minified when processed.
|
48
|
+
# intermediate: - Boolean specifying if the asset exists solely to provide an intermediate form (e.g.
|
49
|
+
# compiled) for another Asset instance.
|
51
50
|
def initialize(path, file, darkroom, prefix: nil, entry: true, minify: false, intermediate: false)
|
52
51
|
@path = path
|
53
52
|
@dir = File.dirname(path)
|
@@ -65,7 +64,8 @@ class Darkroom
|
|
65
64
|
|
66
65
|
if @delegate.compile_delegate && !intermediate
|
67
66
|
@delegate = @delegate.compile_delegate
|
68
|
-
@intermediate_asset = Asset.new(
|
67
|
+
@intermediate_asset = Asset.new(
|
68
|
+
@path, @file, @darkroom,
|
69
69
|
prefix: @prefix,
|
70
70
|
entry: false,
|
71
71
|
minify: false,
|
@@ -77,12 +77,13 @@ class Darkroom
|
|
77
77
|
clear
|
78
78
|
end
|
79
79
|
|
80
|
-
|
81
|
-
#
|
82
|
-
#
|
83
|
-
# (if
|
84
|
-
#
|
80
|
+
# Public: Process the asset if it's been modified since the last run (see #modified? for how
|
81
|
+
# modification is determined). The asset file is read from disk, references are substituted (if
|
82
|
+
# supported for the asset type), content is compiled (if required), imports are prefixed to the asset's
|
83
|
+
# own content (if supported), and content is minified (if supported and enabled and the asset is an
|
84
|
+
# entry point).
|
85
85
|
#
|
86
|
+
# Returns nothing.
|
86
87
|
def process
|
87
88
|
return if ran?(:process)
|
88
89
|
|
@@ -90,107 +91,98 @@ class Darkroom
|
|
90
91
|
content if entry?
|
91
92
|
end
|
92
93
|
|
93
|
-
|
94
|
-
# Returns the HTTP MIME type string.
|
94
|
+
# Public: Get the HTTP MIME type string for this asset.
|
95
95
|
#
|
96
|
+
# Returns the String content type from the asset's Delegate.
|
96
97
|
def content_type
|
97
98
|
@delegate.content_type
|
98
99
|
end
|
99
100
|
|
100
|
-
|
101
|
-
# Returns boolean indicating whether or not the asset is binary.
|
101
|
+
# Public: Check if the asset's content is binary.
|
102
102
|
#
|
103
|
+
# Returns the boolean result.
|
103
104
|
def binary?
|
104
|
-
return @
|
105
|
+
return @binary if defined?(@binary)
|
105
106
|
|
106
107
|
type, subtype = content_type.split('/')
|
107
108
|
|
108
|
-
@
|
109
|
+
@binary = type != 'text' && !subtype.include?('json') && !subtype.include?('xml')
|
109
110
|
end
|
110
111
|
|
111
|
-
|
112
|
-
# Returns boolean indicating whether or not the asset is a font.
|
112
|
+
# Public: Check if the asset is a font.
|
113
113
|
#
|
114
|
+
# Returns the boolean result.
|
114
115
|
def font?
|
115
116
|
defined?(@is_font) ? @is_font : (@is_font = content_type.start_with?('font/'))
|
116
117
|
end
|
117
118
|
|
118
|
-
|
119
|
-
# Returns boolean indicating whether or not the asset is an image.
|
119
|
+
# Public: Check if the asset is an image.
|
120
120
|
#
|
121
|
+
# Returns the boolean result.
|
121
122
|
def image?
|
122
123
|
defined?(@is_image) ? @is_image : (@is_image = content_type.start_with?('image/'))
|
123
124
|
end
|
124
125
|
|
125
|
-
|
126
|
-
# Returns boolean indicating whether or not the asset is an entry point.
|
126
|
+
# Public: Check if the asset is an entry point.
|
127
127
|
#
|
128
|
+
# Returns the boolean result.
|
128
129
|
def entry?
|
129
130
|
@entry
|
130
131
|
end
|
131
132
|
|
132
|
-
|
133
|
-
# DEPRECATED: use #entry? instead. Returns boolean indicating whether or not the asset is marked as
|
134
|
-
# internal.
|
135
|
-
#
|
136
|
-
def internal?
|
137
|
-
Darkroom.deprecated("#{self.class.name}#internal? is deprecated: use #entry? instead")
|
138
|
-
|
139
|
-
!entry?
|
140
|
-
end
|
141
|
-
|
142
|
-
##
|
143
|
-
# Returns boolean indicating whether or not an error was encountered the last time the asset was
|
144
|
-
# processed.
|
133
|
+
# Public: Check if one or more errors were encountered the last time the asset was processed.
|
145
134
|
#
|
135
|
+
# Returns the boolean result.
|
146
136
|
def error?
|
147
|
-
!@errors.empty?
|
137
|
+
@errors && !@errors.empty?
|
148
138
|
end
|
149
139
|
|
150
|
-
|
151
|
-
# Returns ProcessingError wrapper of all errors if any exist, or nil if there are none.
|
140
|
+
# Public: Get a single error wrapper object for all errors.
|
152
141
|
#
|
142
|
+
# Returns a ProcessingError if one or more errors exit or nil otherwise.
|
153
143
|
def error
|
154
|
-
@error ||=
|
144
|
+
@error ||= error? ? ProcessingError.new(@errors) : nil
|
155
145
|
end
|
156
146
|
|
157
|
-
|
158
|
-
# Returns hash of content.
|
147
|
+
# Public: Get an MD5 hash of the asset's content.
|
159
148
|
#
|
149
|
+
# Returns the String hash.
|
160
150
|
def fingerprint
|
161
151
|
content
|
162
152
|
|
163
153
|
@fingerprint
|
164
154
|
end
|
165
155
|
|
166
|
-
|
167
|
-
# Returns versioned path.
|
156
|
+
# Public: Get the versioned path of the asset (includes the fingerprint).
|
168
157
|
#
|
158
|
+
# Returns the String versioned path.
|
169
159
|
def path_versioned
|
170
160
|
content
|
171
161
|
|
172
162
|
@path_versioned
|
173
163
|
end
|
174
164
|
|
175
|
-
|
176
|
-
# Returns appropriate HTTP headers.
|
165
|
+
# Public: Get the asset's HTTP headers.
|
177
166
|
#
|
178
|
-
#
|
167
|
+
# versioned: - Boolean indicating if this is for the versioned or unversioned asset path. If true,
|
168
|
+
# a Cache-Control header with max-age is included; if false, an ETag header is used.
|
179
169
|
#
|
170
|
+
# Returns a Hash of String HTTP header names and String values.
|
180
171
|
def headers(versioned: true)
|
181
172
|
{
|
182
173
|
'Content-Type' => content_type,
|
183
174
|
'Cache-Control' => ('public, max-age=31536000' if versioned),
|
184
|
-
'ETag' => ("\"#{fingerprint}\""
|
175
|
+
'ETag' => ("\"#{fingerprint}\"" unless versioned),
|
185
176
|
}.compact!
|
186
177
|
end
|
187
178
|
|
188
|
-
|
189
|
-
# Returns subresource integrity string.
|
179
|
+
# Public: Get a subresource integrity string (SHA digest).
|
190
180
|
#
|
191
|
-
#
|
192
|
-
#
|
181
|
+
# algorithm - Symbol hash algorithm name to use to generate the integrity string (must be one of
|
182
|
+
# :sha256, :sha384, :sha512).
|
193
183
|
#
|
184
|
+
# Returns the String SHA digest.
|
185
|
+
# Raises RuntimeError if the request algorithm is not valid.
|
194
186
|
def integrity(algorithm = :sha384)
|
195
187
|
@integrity[algorithm] ||= "#{algorithm}-#{Base64.strict_encode64(
|
196
188
|
case algorithm
|
@@ -202,11 +194,11 @@ class Darkroom
|
|
202
194
|
)}".freeze
|
203
195
|
end
|
204
196
|
|
205
|
-
|
206
|
-
# Returns full asset content.
|
197
|
+
# Public: Get the full asset content, including imports and asset reference content substitutions.
|
207
198
|
#
|
208
|
-
#
|
199
|
+
# minified: - Boolean specifying if the minified version is desired.
|
209
200
|
#
|
201
|
+
# Returns the String asset content, minified if requested (and the asset is minifiable).
|
210
202
|
def content(minified: @minify)
|
211
203
|
unless ran?(:content)
|
212
204
|
compile
|
@@ -231,7 +223,7 @@ class Darkroom
|
|
231
223
|
)
|
232
224
|
|
233
225
|
@content = finalized if finalized.kind_of?(String)
|
234
|
-
rescue => e
|
226
|
+
rescue StandardError => e
|
235
227
|
@errors << e
|
236
228
|
end
|
237
229
|
end
|
@@ -243,7 +235,7 @@ class Darkroom
|
|
243
235
|
path: @path,
|
244
236
|
content: @content,
|
245
237
|
)
|
246
|
-
rescue => e
|
238
|
+
rescue StandardError => e
|
247
239
|
@errors << e
|
248
240
|
end
|
249
241
|
end
|
@@ -257,36 +249,39 @@ class Darkroom
|
|
257
249
|
@content_minified.freeze
|
258
250
|
end
|
259
251
|
|
260
|
-
|
261
|
-
# Returns high-level object info string.
|
252
|
+
# Public: Get a high-level object info string about this Asset instance.
|
262
253
|
#
|
254
|
+
# Returns the String.
|
263
255
|
def inspect
|
264
|
-
"#<#{self.class}
|
265
|
-
"@
|
266
|
-
"@
|
267
|
-
"@
|
268
|
-
"@
|
269
|
-
"@
|
270
|
-
"@
|
271
|
-
"@
|
272
|
-
"@
|
273
|
-
"@
|
274
|
-
"@
|
275
|
-
"@
|
256
|
+
"#<#{self.class} " \
|
257
|
+
"@delegate=#{@delegate.inspect}, " \
|
258
|
+
"@dir=#{@dir.inspect}, " \
|
259
|
+
"@entry=#{@entry.inspect}, " \
|
260
|
+
"@errors=#{@errors.inspect}, " \
|
261
|
+
"@extension=#{@extension.inspect}, " \
|
262
|
+
"@file=#{@file.inspect}, " \
|
263
|
+
"@fingerprint=#{@fingerprint.inspect}, " \
|
264
|
+
"@minify=#{@minify.inspect}, " \
|
265
|
+
"@modified=#{@modified.inspect}, " \
|
266
|
+
"@mtime=#{@mtime.inspect}, " \
|
267
|
+
"@path=#{@path.inspect}, " \
|
268
|
+
"@path_unversioned=#{@path_unversioned.inspect}, " \
|
269
|
+
"@path_versioned=#{@path_versioned.inspect}, " \
|
270
|
+
"@prefix=#{@prefix.inspect}" \
|
276
271
|
'>'
|
277
272
|
end
|
278
273
|
|
279
274
|
protected
|
280
275
|
|
281
|
-
|
282
|
-
# Returns true if the asset or any of its dependencies were modified since last processed, or if an
|
276
|
+
# Internal: Check if the asset or any of its dependencies were modified since last processed, or if an
|
283
277
|
# error was recorded during the last processing run.
|
284
278
|
#
|
279
|
+
# Returns the boolean result.
|
285
280
|
def modified?
|
286
281
|
@modified_key == @darkroom.process_key ? (return @modified) : @modified_key = @darkroom.process_key
|
287
282
|
|
288
283
|
begin
|
289
|
-
@modified =
|
284
|
+
@modified = error?
|
290
285
|
@modified ||= (@mtime != (@mtime = File.mtime(@file)))
|
291
286
|
@modified ||= @intermediate_asset.modified? if @intermediate_asset
|
292
287
|
@modified ||= dependencies.any? { |d| d.modified? }
|
@@ -299,9 +294,9 @@ class Darkroom
|
|
299
294
|
end
|
300
295
|
end
|
301
296
|
|
302
|
-
|
303
|
-
# Clears content, dependencies, and errors so asset is ready for (re)processing.
|
297
|
+
# Internal: Clear content, dependencies, and errors so asset is ready for (re)processing.
|
304
298
|
#
|
299
|
+
# Returns nothing.
|
305
300
|
def clear
|
306
301
|
return if ran?(:clear)
|
307
302
|
|
@@ -325,9 +320,9 @@ class Darkroom
|
|
325
320
|
@errors = []
|
326
321
|
end
|
327
322
|
|
328
|
-
|
329
|
-
# Reads the asset file into memory.
|
323
|
+
# Internal: Read the asset file into memory.
|
330
324
|
#
|
325
|
+
# Returns nothing.
|
331
326
|
def read
|
332
327
|
return if ran?(:read)
|
333
328
|
|
@@ -346,9 +341,9 @@ class Darkroom
|
|
346
341
|
end
|
347
342
|
end
|
348
343
|
|
349
|
-
|
350
|
-
# Parses own content to build list of imports and references.
|
344
|
+
# Internal: Parse the asset's own content to build the lists of imports and references.
|
351
345
|
#
|
346
|
+
# Returns nothing.
|
352
347
|
def parse
|
353
348
|
return if ran?(:parse)
|
354
349
|
|
@@ -359,7 +354,7 @@ class Darkroom
|
|
359
354
|
match = Regexp.last_match
|
360
355
|
asset = nil
|
361
356
|
|
362
|
-
if kind
|
357
|
+
if BUILT_IN_PARSE_KINDS.include?(kind)
|
363
358
|
path = File.expand_path(match[:path], @dir)
|
364
359
|
asset = @darkroom.manifest(path)
|
365
360
|
|
@@ -372,18 +367,18 @@ class Darkroom
|
|
372
367
|
end
|
373
368
|
end
|
374
369
|
|
375
|
-
|
376
|
-
# Returns direct dependencies (ones explicitly specified in the asset's own content.)
|
370
|
+
# Internal: Get direct dependencies (ones explicitly specified in the asset's own content).
|
377
371
|
#
|
372
|
+
# Returns an Array of Asset objects.
|
378
373
|
def own_dependencies
|
379
374
|
parse
|
380
375
|
|
381
376
|
@own_dependencies
|
382
377
|
end
|
383
378
|
|
384
|
-
|
385
|
-
# Returns all dependencies (including dependencies of dependencies).
|
379
|
+
# Internal: Get all dependencies (including dependencies of dependencies).
|
386
380
|
#
|
381
|
+
# Returns an Array of Asset objects.
|
387
382
|
def dependencies
|
388
383
|
unless ran?(:dependencies)
|
389
384
|
parse
|
@@ -393,18 +388,18 @@ class Darkroom
|
|
393
388
|
@dependencies
|
394
389
|
end
|
395
390
|
|
396
|
-
|
397
|
-
# Returns direct imports (ones explicitly specified in the asset's own content.)
|
391
|
+
# Internal: Get direct imports (ones explicitly specified in the asset's own content).
|
398
392
|
#
|
393
|
+
# Returns an Array of Asset objects.
|
399
394
|
def own_imports
|
400
395
|
parse
|
401
396
|
|
402
397
|
@own_imports
|
403
398
|
end
|
404
399
|
|
405
|
-
|
406
|
-
# Returns all imports (including imports of imports).
|
400
|
+
# Internal: Get all imports (including imports of imports).
|
407
401
|
#
|
402
|
+
# Returns an Array of Asset objects.
|
408
403
|
def imports
|
409
404
|
unless ran?(:imports)
|
410
405
|
parse
|
@@ -414,18 +409,18 @@ class Darkroom
|
|
414
409
|
@imports
|
415
410
|
end
|
416
411
|
|
417
|
-
|
418
|
-
# Performs import and reference substitutions based on parse matches.
|
412
|
+
# Internal: Perform import and reference substitutions based on parse matches.
|
419
413
|
#
|
414
|
+
# Returns nothing.
|
420
415
|
def substitute
|
421
416
|
return if ran?(:substitute)
|
422
417
|
|
423
418
|
parse
|
424
419
|
substitutions = []
|
425
420
|
|
426
|
-
@parse_matches.sort_by! { |
|
427
|
-
format = nil
|
421
|
+
@parse_matches.sort_by! { |_kind, match, _asset| match.begin(0) }
|
428
422
|
|
423
|
+
@parse_matches.each do |kind, match, asset|
|
429
424
|
handler = @delegate.handler(kind)
|
430
425
|
handler_args = {
|
431
426
|
parse_data: @parse_data,
|
@@ -433,24 +428,29 @@ class Darkroom
|
|
433
428
|
}
|
434
429
|
handler_args[:asset] = asset if asset
|
435
430
|
|
436
|
-
if !asset && (kind
|
437
|
-
add_parse_error(
|
431
|
+
if !asset && BUILT_IN_PARSE_KINDS.include?(kind)
|
432
|
+
add_parse_error(:not_found, match)
|
438
433
|
next
|
439
434
|
elsif kind == :reference
|
435
|
+
entity = match[:entity]
|
440
436
|
format = match[:format]
|
441
|
-
|
437
|
+
|
438
|
+
allowed_formats = REFERENCE_FORMATS[entity]
|
439
|
+
format = allowed_formats&.first if format.nil? || format == ''
|
442
440
|
|
443
441
|
handler_args[:format] = format
|
444
442
|
|
445
443
|
if asset.dependencies.include?(self)
|
446
|
-
add_parse_error(
|
444
|
+
add_parse_error(:circular_reference, match)
|
445
|
+
next
|
446
|
+
elsif allowed_formats.nil?
|
447
|
+
add_parse_error(:unrecognized_reference_entity, match)
|
447
448
|
next
|
448
|
-
elsif !
|
449
|
-
|
450
|
-
add_parse_error(match, "Invalid reference format '#{format}' (must be one of '#{formats}')")
|
449
|
+
elsif !allowed_formats.include?(format)
|
450
|
+
add_parse_error(:unrecognized_reference_format, match)
|
451
451
|
next
|
452
|
-
elsif
|
453
|
-
add_parse_error(
|
452
|
+
elsif entity == 'content' && format != 'base64' && asset.binary?
|
453
|
+
add_parse_error(:format_not_base64, match)
|
454
454
|
next
|
455
455
|
end
|
456
456
|
end
|
@@ -459,10 +459,10 @@ class Darkroom
|
|
459
459
|
substitution, start, finish = handler&.call(**handler_args)
|
460
460
|
|
461
461
|
min_start, max_finish = match.offset(0)
|
462
|
-
start ||=
|
463
|
-
finish ||=
|
464
|
-
start =
|
465
|
-
finish =
|
462
|
+
start ||= !format || format == 'displace' ? min_start : match.begin(:quoted)
|
463
|
+
finish ||= !format || format == 'displace' ? max_finish : match.end(:quoted)
|
464
|
+
start = start.clamp(min_start, max_finish)
|
465
|
+
finish = finish.clamp(min_start, max_finish)
|
466
466
|
|
467
467
|
if kind == :reference
|
468
468
|
case "#{match[:entity]}-#{format}"
|
@@ -487,7 +487,7 @@ class Darkroom
|
|
487
487
|
nil
|
488
488
|
end
|
489
489
|
|
490
|
-
add_parse_error(
|
490
|
+
add_parse_error(error, match) if error
|
491
491
|
end
|
492
492
|
|
493
493
|
substitutions.reverse_each do |content, start, finish|
|
@@ -495,9 +495,9 @@ class Darkroom
|
|
495
495
|
end
|
496
496
|
end
|
497
497
|
|
498
|
-
|
499
|
-
# Compiles the asset if compilation is supported for the asset's type.
|
498
|
+
# Internal: Compile the asset if compilation is supported for the asset's type.
|
500
499
|
#
|
500
|
+
# Returns nothing.
|
501
501
|
def compile
|
502
502
|
return if ran?(:compile)
|
503
503
|
|
@@ -511,16 +511,16 @@ class Darkroom
|
|
511
511
|
)
|
512
512
|
|
513
513
|
@own_content = compiled if compiled.kind_of?(String)
|
514
|
-
rescue => e
|
514
|
+
rescue StandardError => e
|
515
515
|
@errors << e
|
516
516
|
ensure
|
517
517
|
@own_content.freeze
|
518
518
|
end
|
519
519
|
end
|
520
520
|
|
521
|
-
|
522
|
-
# Returns the processed content of the asset without dependencies concatenated.
|
521
|
+
# Internal: Get the processed content of the asset without dependencies concatenated.
|
523
522
|
#
|
523
|
+
# Returns the String result.
|
524
524
|
def own_content
|
525
525
|
compile
|
526
526
|
|
@@ -529,37 +529,35 @@ class Darkroom
|
|
529
529
|
|
530
530
|
private
|
531
531
|
|
532
|
-
|
533
|
-
#
|
534
|
-
# MissingLibraryError if library cannot be loaded.
|
532
|
+
# Internal: Require any libraries necessary for compiling, finalizing, and minifying the asset based on
|
533
|
+
# its type.
|
535
534
|
#
|
536
|
-
# Darkroom does not explicitly depend on any libraries necessary for asset compilation or
|
537
|
-
#
|
538
|
-
# using Darkroom to specify any needed
|
539
|
-
#
|
535
|
+
# Darkroom does not explicitly depend on any libraries necessary for asset compilation, finalization, or
|
536
|
+
# minification. This is because not every app will use every kind of asset or use minification. It is
|
537
|
+
# instead up to each app using Darkroom to specify any needed libraries as direct dependencies (e.g. add
|
538
|
+
# gem('terser') to the app's Gemfile if JavaScript minification is desired).
|
540
539
|
#
|
540
|
+
# Returns nothing.
|
541
|
+
# Raises MissingLibraryError if a library cannot be loaded.
|
541
542
|
def require_libs
|
542
|
-
|
543
|
-
|
544
|
-
rescue LoadError
|
545
|
-
compile_load_error = true
|
546
|
-
end
|
543
|
+
Delegate::LIB_REQUIRES.each do |need|
|
544
|
+
next if need == :minify && !@minify
|
547
545
|
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
546
|
+
begin
|
547
|
+
lib = @delegate.send(:"#{need}_lib")
|
548
|
+
require(lib) if lib
|
549
|
+
rescue LoadError
|
550
|
+
raise(MissingLibraryError.new(lib, need, @extension), cause: nil)
|
551
|
+
end
|
552
552
|
end
|
553
|
-
|
554
|
-
raise(MissingLibraryError.new(@delegate.compile_lib, 'compile', @extension)) if compile_load_error
|
555
|
-
raise(MissingLibraryError.new(@delegate.minify_lib, 'minify', @extension)) if minify_load_error
|
556
553
|
end
|
557
554
|
|
558
|
-
|
559
|
-
#
|
555
|
+
# Internal: Check if a method has already been run during the current round of processing and mark it as
|
556
|
+
# having been run if not.
|
560
557
|
#
|
561
|
-
#
|
558
|
+
# name - Symbol name of the method.
|
562
559
|
#
|
560
|
+
# Returns the boolean result.
|
563
561
|
def ran?(name)
|
564
562
|
modified?
|
565
563
|
|
@@ -571,11 +569,11 @@ class Darkroom
|
|
571
569
|
end
|
572
570
|
end
|
573
571
|
|
574
|
-
|
575
|
-
# Utility method used by #dependencies and #imports to recursively build arrays.
|
572
|
+
# Internal: Recursively build an array of Asset objects (used by #dependencies and #imports).
|
576
573
|
#
|
577
|
-
#
|
574
|
+
# name - Symbol name of the array to accumulate (:dependencies or :imports).
|
578
575
|
#
|
576
|
+
# Returns an Array of Asset objects.
|
579
577
|
def accumulate(name)
|
580
578
|
done = Set.new
|
581
579
|
assets = [self]
|
@@ -593,28 +591,42 @@ class Darkroom
|
|
593
591
|
assets
|
594
592
|
end
|
595
593
|
|
596
|
-
|
597
|
-
#
|
598
|
-
#
|
599
|
-
#
|
600
|
-
#
|
601
|
-
#
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
594
|
+
# Internal: Create a parse error of the appropriate class and append it to the errors array.
|
595
|
+
#
|
596
|
+
# error - Symbol error type or String error message.
|
597
|
+
# match - MatchData object for where the parse error occurred.
|
598
|
+
#
|
599
|
+
# Returns nothing.
|
600
|
+
# Raises RuntimeError if error is not a String or recognized Symbol error name.
|
601
|
+
def add_parse_error(error, match)
|
602
|
+
klass = AssetError
|
603
|
+
args = [match[0].strip]
|
604
|
+
|
605
|
+
case error
|
606
|
+
when :not_found
|
607
|
+
path = match[:path]
|
608
|
+
delegate = Darkroom.delegate(File.extname(path)) if path
|
609
|
+
klass = delegate ? AssetNotFoundError : UnrecognizedExtensionError
|
610
|
+
args.clear << path
|
611
|
+
when :circular_reference
|
612
|
+
klass = CircularReferenceError
|
613
|
+
when :unrecognized_reference_entity
|
614
|
+
entity = match[:entity].nil? ? 'nil' : "'#{match[:entity]}'"
|
615
|
+
allowed = "'#{Asset::REFERENCE_FORMATS.keys.join("', '")}'"
|
616
|
+
message = "Invalid reference entity #{entity} (must be one of #{allowed})"
|
617
|
+
when :unrecognized_reference_format
|
618
|
+
entity = match[:entity]
|
619
|
+
format = match[:format].nil? ? 'nil' : "'#{match[:format]}'"
|
620
|
+
allowed = "'#{Asset::REFERENCE_FORMATS[entity].join("', '")}'"
|
621
|
+
message = "Invalid reference format #{format} (must be one of #{allowed})"
|
622
|
+
when :format_not_base64
|
623
|
+
message = 'Base64 encoding is required for binary assets'
|
609
624
|
else
|
610
|
-
|
611
|
-
klass = AssetError
|
612
|
-
args << error
|
613
|
-
end
|
614
|
-
|
615
|
-
args << match[0].strip
|
625
|
+
message = error.to_s
|
616
626
|
end
|
617
627
|
|
628
|
+
args.unshift(message) if message
|
629
|
+
|
618
630
|
@errors << klass.new(*args, @path, @own_content[0..match.begin(:path)].count("\n") + 1)
|
619
631
|
end
|
620
632
|
end
|