darkroom 0.0.9 → 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 +9 -0
- data/README.md +175 -131
- data/VERSION +1 -1
- data/lib/darkroom/asset.rb +173 -151
- data/lib/darkroom/darkroom.rb +140 -124
- data/lib/darkroom/delegate.rb +208 -101
- 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 +4 -6
- metadata +17 -21
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,97 +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
|
-
# Returns boolean indicating whether or not an error was encountered the last time the asset was
|
134
|
-
# processed.
|
133
|
+
# Public: Check if one or more errors were encountered the last time the asset was processed.
|
135
134
|
#
|
135
|
+
# Returns the boolean result.
|
136
136
|
def error?
|
137
137
|
@errors && !@errors.empty?
|
138
138
|
end
|
139
139
|
|
140
|
-
|
141
|
-
# 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.
|
142
141
|
#
|
142
|
+
# Returns a ProcessingError if one or more errors exit or nil otherwise.
|
143
143
|
def error
|
144
144
|
@error ||= error? ? ProcessingError.new(@errors) : nil
|
145
145
|
end
|
146
146
|
|
147
|
-
|
148
|
-
# Returns hash of content.
|
147
|
+
# Public: Get an MD5 hash of the asset's content.
|
149
148
|
#
|
149
|
+
# Returns the String hash.
|
150
150
|
def fingerprint
|
151
151
|
content
|
152
152
|
|
153
153
|
@fingerprint
|
154
154
|
end
|
155
155
|
|
156
|
-
|
157
|
-
# Returns versioned path.
|
156
|
+
# Public: Get the versioned path of the asset (includes the fingerprint).
|
158
157
|
#
|
158
|
+
# Returns the String versioned path.
|
159
159
|
def path_versioned
|
160
160
|
content
|
161
161
|
|
162
162
|
@path_versioned
|
163
163
|
end
|
164
164
|
|
165
|
-
|
166
|
-
# Returns appropriate HTTP headers.
|
165
|
+
# Public: Get the asset's HTTP headers.
|
167
166
|
#
|
168
|
-
#
|
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.
|
169
169
|
#
|
170
|
+
# Returns a Hash of String HTTP header names and String values.
|
170
171
|
def headers(versioned: true)
|
171
172
|
{
|
172
173
|
'Content-Type' => content_type,
|
173
174
|
'Cache-Control' => ('public, max-age=31536000' if versioned),
|
174
|
-
'ETag' => ("\"#{fingerprint}\""
|
175
|
+
'ETag' => ("\"#{fingerprint}\"" unless versioned),
|
175
176
|
}.compact!
|
176
177
|
end
|
177
178
|
|
178
|
-
|
179
|
-
# Returns subresource integrity string.
|
179
|
+
# Public: Get a subresource integrity string (SHA digest).
|
180
180
|
#
|
181
|
-
#
|
182
|
-
#
|
181
|
+
# algorithm - Symbol hash algorithm name to use to generate the integrity string (must be one of
|
182
|
+
# :sha256, :sha384, :sha512).
|
183
183
|
#
|
184
|
+
# Returns the String SHA digest.
|
185
|
+
# Raises RuntimeError if the request algorithm is not valid.
|
184
186
|
def integrity(algorithm = :sha384)
|
185
187
|
@integrity[algorithm] ||= "#{algorithm}-#{Base64.strict_encode64(
|
186
188
|
case algorithm
|
@@ -192,11 +194,11 @@ class Darkroom
|
|
192
194
|
)}".freeze
|
193
195
|
end
|
194
196
|
|
195
|
-
|
196
|
-
# Returns full asset content.
|
197
|
+
# Public: Get the full asset content, including imports and asset reference content substitutions.
|
197
198
|
#
|
198
|
-
#
|
199
|
+
# minified: - Boolean specifying if the minified version is desired.
|
199
200
|
#
|
201
|
+
# Returns the String asset content, minified if requested (and the asset is minifiable).
|
200
202
|
def content(minified: @minify)
|
201
203
|
unless ran?(:content)
|
202
204
|
compile
|
@@ -221,7 +223,7 @@ class Darkroom
|
|
221
223
|
)
|
222
224
|
|
223
225
|
@content = finalized if finalized.kind_of?(String)
|
224
|
-
rescue => e
|
226
|
+
rescue StandardError => e
|
225
227
|
@errors << e
|
226
228
|
end
|
227
229
|
end
|
@@ -233,7 +235,7 @@ class Darkroom
|
|
233
235
|
path: @path,
|
234
236
|
content: @content,
|
235
237
|
)
|
236
|
-
rescue => e
|
238
|
+
rescue StandardError => e
|
237
239
|
@errors << e
|
238
240
|
end
|
239
241
|
end
|
@@ -247,31 +249,34 @@ class Darkroom
|
|
247
249
|
@content_minified.freeze
|
248
250
|
end
|
249
251
|
|
250
|
-
|
251
|
-
# Returns high-level object info string.
|
252
|
+
# Public: Get a high-level object info string about this Asset instance.
|
252
253
|
#
|
254
|
+
# Returns the String.
|
253
255
|
def inspect
|
254
|
-
"#<#{self.class} "\
|
255
|
-
"@
|
256
|
-
"@
|
257
|
-
"@
|
258
|
-
"@
|
259
|
-
"@
|
260
|
-
"@
|
261
|
-
"@
|
262
|
-
"@
|
263
|
-
"@
|
264
|
-
"@
|
265
|
-
"@
|
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}" \
|
266
271
|
'>'
|
267
272
|
end
|
268
273
|
|
269
274
|
protected
|
270
275
|
|
271
|
-
|
272
|
-
# 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
|
273
277
|
# error was recorded during the last processing run.
|
274
278
|
#
|
279
|
+
# Returns the boolean result.
|
275
280
|
def modified?
|
276
281
|
@modified_key == @darkroom.process_key ? (return @modified) : @modified_key = @darkroom.process_key
|
277
282
|
|
@@ -289,9 +294,9 @@ class Darkroom
|
|
289
294
|
end
|
290
295
|
end
|
291
296
|
|
292
|
-
|
293
|
-
# 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.
|
294
298
|
#
|
299
|
+
# Returns nothing.
|
295
300
|
def clear
|
296
301
|
return if ran?(:clear)
|
297
302
|
|
@@ -315,9 +320,9 @@ class Darkroom
|
|
315
320
|
@errors = []
|
316
321
|
end
|
317
322
|
|
318
|
-
|
319
|
-
# Reads the asset file into memory.
|
323
|
+
# Internal: Read the asset file into memory.
|
320
324
|
#
|
325
|
+
# Returns nothing.
|
321
326
|
def read
|
322
327
|
return if ran?(:read)
|
323
328
|
|
@@ -336,9 +341,9 @@ class Darkroom
|
|
336
341
|
end
|
337
342
|
end
|
338
343
|
|
339
|
-
|
340
|
-
# 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.
|
341
345
|
#
|
346
|
+
# Returns nothing.
|
342
347
|
def parse
|
343
348
|
return if ran?(:parse)
|
344
349
|
|
@@ -349,7 +354,7 @@ class Darkroom
|
|
349
354
|
match = Regexp.last_match
|
350
355
|
asset = nil
|
351
356
|
|
352
|
-
if kind
|
357
|
+
if BUILT_IN_PARSE_KINDS.include?(kind)
|
353
358
|
path = File.expand_path(match[:path], @dir)
|
354
359
|
asset = @darkroom.manifest(path)
|
355
360
|
|
@@ -362,18 +367,18 @@ class Darkroom
|
|
362
367
|
end
|
363
368
|
end
|
364
369
|
|
365
|
-
|
366
|
-
# 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).
|
367
371
|
#
|
372
|
+
# Returns an Array of Asset objects.
|
368
373
|
def own_dependencies
|
369
374
|
parse
|
370
375
|
|
371
376
|
@own_dependencies
|
372
377
|
end
|
373
378
|
|
374
|
-
|
375
|
-
# Returns all dependencies (including dependencies of dependencies).
|
379
|
+
# Internal: Get all dependencies (including dependencies of dependencies).
|
376
380
|
#
|
381
|
+
# Returns an Array of Asset objects.
|
377
382
|
def dependencies
|
378
383
|
unless ran?(:dependencies)
|
379
384
|
parse
|
@@ -383,18 +388,18 @@ class Darkroom
|
|
383
388
|
@dependencies
|
384
389
|
end
|
385
390
|
|
386
|
-
|
387
|
-
# 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).
|
388
392
|
#
|
393
|
+
# Returns an Array of Asset objects.
|
389
394
|
def own_imports
|
390
395
|
parse
|
391
396
|
|
392
397
|
@own_imports
|
393
398
|
end
|
394
399
|
|
395
|
-
|
396
|
-
# Returns all imports (including imports of imports).
|
400
|
+
# Internal: Get all imports (including imports of imports).
|
397
401
|
#
|
402
|
+
# Returns an Array of Asset objects.
|
398
403
|
def imports
|
399
404
|
unless ran?(:imports)
|
400
405
|
parse
|
@@ -404,18 +409,18 @@ class Darkroom
|
|
404
409
|
@imports
|
405
410
|
end
|
406
411
|
|
407
|
-
|
408
|
-
# Performs import and reference substitutions based on parse matches.
|
412
|
+
# Internal: Perform import and reference substitutions based on parse matches.
|
409
413
|
#
|
414
|
+
# Returns nothing.
|
410
415
|
def substitute
|
411
416
|
return if ran?(:substitute)
|
412
417
|
|
413
418
|
parse
|
414
419
|
substitutions = []
|
415
420
|
|
416
|
-
@parse_matches.sort_by! { |
|
417
|
-
format = nil
|
421
|
+
@parse_matches.sort_by! { |_kind, match, _asset| match.begin(0) }
|
418
422
|
|
423
|
+
@parse_matches.each do |kind, match, asset|
|
419
424
|
handler = @delegate.handler(kind)
|
420
425
|
handler_args = {
|
421
426
|
parse_data: @parse_data,
|
@@ -423,24 +428,29 @@ class Darkroom
|
|
423
428
|
}
|
424
429
|
handler_args[:asset] = asset if asset
|
425
430
|
|
426
|
-
if !asset && (kind
|
427
|
-
add_parse_error(
|
431
|
+
if !asset && BUILT_IN_PARSE_KINDS.include?(kind)
|
432
|
+
add_parse_error(:not_found, match)
|
428
433
|
next
|
429
434
|
elsif kind == :reference
|
435
|
+
entity = match[:entity]
|
430
436
|
format = match[:format]
|
431
|
-
|
437
|
+
|
438
|
+
allowed_formats = REFERENCE_FORMATS[entity]
|
439
|
+
format = allowed_formats&.first if format.nil? || format == ''
|
432
440
|
|
433
441
|
handler_args[:format] = format
|
434
442
|
|
435
443
|
if asset.dependencies.include?(self)
|
436
|
-
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)
|
437
448
|
next
|
438
|
-
elsif !
|
439
|
-
|
440
|
-
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)
|
441
451
|
next
|
442
|
-
elsif
|
443
|
-
add_parse_error(
|
452
|
+
elsif entity == 'content' && format != 'base64' && asset.binary?
|
453
|
+
add_parse_error(:format_not_base64, match)
|
444
454
|
next
|
445
455
|
end
|
446
456
|
end
|
@@ -449,10 +459,10 @@ class Darkroom
|
|
449
459
|
substitution, start, finish = handler&.call(**handler_args)
|
450
460
|
|
451
461
|
min_start, max_finish = match.offset(0)
|
452
|
-
start ||=
|
453
|
-
finish ||=
|
454
|
-
start =
|
455
|
-
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)
|
456
466
|
|
457
467
|
if kind == :reference
|
458
468
|
case "#{match[:entity]}-#{format}"
|
@@ -477,7 +487,7 @@ class Darkroom
|
|
477
487
|
nil
|
478
488
|
end
|
479
489
|
|
480
|
-
add_parse_error(
|
490
|
+
add_parse_error(error, match) if error
|
481
491
|
end
|
482
492
|
|
483
493
|
substitutions.reverse_each do |content, start, finish|
|
@@ -485,9 +495,9 @@ class Darkroom
|
|
485
495
|
end
|
486
496
|
end
|
487
497
|
|
488
|
-
|
489
|
-
# 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.
|
490
499
|
#
|
500
|
+
# Returns nothing.
|
491
501
|
def compile
|
492
502
|
return if ran?(:compile)
|
493
503
|
|
@@ -501,16 +511,16 @@ class Darkroom
|
|
501
511
|
)
|
502
512
|
|
503
513
|
@own_content = compiled if compiled.kind_of?(String)
|
504
|
-
rescue => e
|
514
|
+
rescue StandardError => e
|
505
515
|
@errors << e
|
506
516
|
ensure
|
507
517
|
@own_content.freeze
|
508
518
|
end
|
509
519
|
end
|
510
520
|
|
511
|
-
|
512
|
-
# Returns the processed content of the asset without dependencies concatenated.
|
521
|
+
# Internal: Get the processed content of the asset without dependencies concatenated.
|
513
522
|
#
|
523
|
+
# Returns the String result.
|
514
524
|
def own_content
|
515
525
|
compile
|
516
526
|
|
@@ -519,37 +529,35 @@ class Darkroom
|
|
519
529
|
|
520
530
|
private
|
521
531
|
|
522
|
-
|
523
|
-
#
|
524
|
-
# MissingLibraryError if library cannot be loaded.
|
532
|
+
# Internal: Require any libraries necessary for compiling, finalizing, and minifying the asset based on
|
533
|
+
# its type.
|
525
534
|
#
|
526
|
-
# Darkroom does not explicitly depend on any libraries necessary for asset compilation or
|
527
|
-
#
|
528
|
-
# using Darkroom to specify any needed
|
529
|
-
#
|
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).
|
530
539
|
#
|
540
|
+
# Returns nothing.
|
541
|
+
# Raises MissingLibraryError if a library cannot be loaded.
|
531
542
|
def require_libs
|
532
|
-
|
533
|
-
|
534
|
-
rescue LoadError
|
535
|
-
compile_load_error = true
|
536
|
-
end
|
543
|
+
Delegate::LIB_REQUIRES.each do |need|
|
544
|
+
next if need == :minify && !@minify
|
537
545
|
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
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
|
542
552
|
end
|
543
|
-
|
544
|
-
raise(MissingLibraryError.new(@delegate.compile_lib, 'compile', @extension)) if compile_load_error
|
545
|
-
raise(MissingLibraryError.new(@delegate.minify_lib, 'minify', @extension)) if minify_load_error
|
546
553
|
end
|
547
554
|
|
548
|
-
|
549
|
-
#
|
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.
|
550
557
|
#
|
551
|
-
#
|
558
|
+
# name - Symbol name of the method.
|
552
559
|
#
|
560
|
+
# Returns the boolean result.
|
553
561
|
def ran?(name)
|
554
562
|
modified?
|
555
563
|
|
@@ -561,11 +569,11 @@ class Darkroom
|
|
561
569
|
end
|
562
570
|
end
|
563
571
|
|
564
|
-
|
565
|
-
# 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).
|
566
573
|
#
|
567
|
-
#
|
574
|
+
# name - Symbol name of the array to accumulate (:dependencies or :imports).
|
568
575
|
#
|
576
|
+
# Returns an Array of Asset objects.
|
569
577
|
def accumulate(name)
|
570
578
|
done = Set.new
|
571
579
|
assets = [self]
|
@@ -583,28 +591,42 @@ class Darkroom
|
|
583
591
|
assets
|
584
592
|
end
|
585
593
|
|
586
|
-
|
587
|
-
#
|
588
|
-
#
|
589
|
-
#
|
590
|
-
#
|
591
|
-
#
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
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'
|
599
624
|
else
|
600
|
-
|
601
|
-
klass = AssetError
|
602
|
-
args << error
|
603
|
-
end
|
604
|
-
|
605
|
-
args << match[0].strip
|
625
|
+
message = error.to_s
|
606
626
|
end
|
607
627
|
|
628
|
+
args.unshift(message) if message
|
629
|
+
|
608
630
|
@errors << klass.new(*args, @path, @own_content[0..match.begin(:path)].count("\n") + 1)
|
609
631
|
end
|
610
632
|
end
|