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/delegate.rb
CHANGED
@@ -1,237 +1,280 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Darkroom
|
2
|
-
##
|
3
4
|
# Holds asset type-specific information and functionality.
|
4
|
-
#
|
5
|
-
# [minify_lib:] Name of a library to +require+ that is needed by the +minify+ lambda (optional).
|
6
|
-
# [minify:] Lambda to call that will return the minified version of the asset's content (optional). One
|
7
|
-
# argument is passed when called:
|
8
|
-
# * +content+ - Content to minify.
|
9
|
-
#
|
10
5
|
class Delegate
|
11
|
-
[
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
6
|
+
IMPORT_REGEX_CAPTURES = %w[path].freeze
|
7
|
+
REFERENCE_REGEX_CAPTURES = %w[quote path quoted entity format].freeze
|
8
|
+
LIB_REQUIRES = [:compile, :finalize, :minify].freeze
|
9
|
+
|
10
|
+
@content_type = nil
|
11
|
+
@parsers = nil
|
12
|
+
@compile_lib = nil
|
13
|
+
@compile_delegate = nil
|
14
|
+
@compile_handler = nil
|
15
|
+
@finalize_lib = nil
|
16
|
+
@finalize_handler = nil
|
17
|
+
@minify_lib = nil
|
18
|
+
@minify_handler = nil
|
19
|
+
|
20
|
+
# Public: Set and/or get the HTTP MIME type string, falling back to that of the parent class.
|
21
|
+
#
|
22
|
+
# Returns the String content type.
|
23
|
+
def self.content_type(content_type = (get = true; nil))
|
24
|
+
if get
|
25
|
+
defined?(@content_type) ? @content_type : superclass.content_type
|
26
|
+
else
|
27
|
+
@content_type = content_type
|
20
28
|
end
|
21
29
|
end
|
22
30
|
|
23
|
-
|
31
|
+
# Public: Get parsers, falling back to those of the parent class.
|
32
|
+
#
|
33
|
+
# Returns the Array of Proc parsers.
|
34
|
+
def self.parsers
|
35
|
+
defined?(@parsers) ? @parsers : superclass.parsers
|
36
|
+
end
|
24
37
|
|
25
|
-
|
26
|
-
# Sets or returns HTTP MIME type string.
|
38
|
+
# Public: Iterate over each parser.
|
27
39
|
#
|
28
|
-
|
29
|
-
|
40
|
+
# Yields each parser's Symbol kind, Regexp regex, and Proc handler.
|
41
|
+
#
|
42
|
+
# Returns nothing.
|
43
|
+
def self.each_parser
|
44
|
+
parsers&.each do |kind, (regex, handler)|
|
45
|
+
yield(kind, regex, handler)
|
46
|
+
end
|
30
47
|
end
|
31
48
|
|
32
|
-
|
33
|
-
# Configures how imports are handled.
|
49
|
+
# Public: Get the name of the compile library to require, falling back to that of the parent class.
|
34
50
|
#
|
35
|
-
#
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
51
|
+
# Returns the String library name if present or nil otherwise.
|
52
|
+
def self.compile_lib
|
53
|
+
defined?(@compile_lib) ? @compile_lib : superclass.compile_lib
|
54
|
+
end
|
55
|
+
|
56
|
+
# Public: Get the Delegate class used once an asset is compiled, falling back to that of the parent
|
57
|
+
# class.
|
58
|
+
#
|
59
|
+
# Returns the Delegate class if present or nil otherwise.
|
60
|
+
def self.compile_delegate
|
61
|
+
defined?(@compile_delegate) ? @compile_delegate : superclass.compile_delegate
|
62
|
+
end
|
63
|
+
|
64
|
+
# Public: Get the compile handler, falling back to that of the parent class.
|
65
|
+
#
|
66
|
+
# Returns the Proc handler if present or nil otherwise.
|
67
|
+
def self.compile_handler
|
68
|
+
defined?(@compile_handler) ? @compile_handler : superclass.compile_handler
|
69
|
+
end
|
70
|
+
|
71
|
+
# Public: Get the name of the finalize library to require, falling back to that of the parent class.
|
72
|
+
#
|
73
|
+
# Returns the String library name if present or nil otherwise.
|
74
|
+
def self.finalize_lib
|
75
|
+
defined?(@finalize_lib) ? @finalize_lib : superclass.finalize_lib
|
76
|
+
end
|
77
|
+
|
78
|
+
# Public: Get the finalize handler, falling back to that of the parent class.
|
79
|
+
#
|
80
|
+
# Returns the Proc handler if present or nil otherwise.
|
81
|
+
def self.finalize_handler
|
82
|
+
defined?(@finalize_handler) ? @finalize_handler : superclass.finalize_handler
|
83
|
+
end
|
84
|
+
|
85
|
+
# Public: Get the name of the minify library to require, falling back to that of the parent class.
|
86
|
+
#
|
87
|
+
# Returns the String library name if present or nil otherwise.
|
88
|
+
def self.minify_lib
|
89
|
+
defined?(@minify_lib) ? @minify_lib : superclass.minify_lib
|
90
|
+
end
|
91
|
+
|
92
|
+
# Public: Get the minify handler, falling back to that of the parent class.
|
93
|
+
#
|
94
|
+
# Returns the Proc handler if present or nil otherwise.
|
95
|
+
def self.minify_handler
|
96
|
+
defined?(@minify_handler) ? @minify_handler : superclass.minify_handler
|
97
|
+
end
|
98
|
+
|
99
|
+
# Internal: Configure import handling.
|
44
100
|
#
|
101
|
+
# regex - Regexp for finding import statements. Must contain a named components :quote (' or ") and
|
102
|
+
# :path (the path of the asset being imported).
|
103
|
+
# handler - Proc for special handling of import statements (optional), which is passed three keyword
|
104
|
+
# arguments:
|
105
|
+
#
|
106
|
+
# parse_data: - Hash for storing arbitrary data across calls to this and other handlers.
|
107
|
+
# match: - MatchData object from the match against the regex.
|
108
|
+
# asset: - Asset object of the asset being imported.
|
109
|
+
#
|
110
|
+
# Returns nil for default behavior, or a String which is used as the substitution for the text
|
111
|
+
# matched by the regex. The portion of the matched text that is replaced can optionally be
|
112
|
+
# changed by returning second and third Integer values specifying start and end indexes
|
113
|
+
# within the regex match (e.g. ['my substitution', match.begin(:path) + 1,
|
114
|
+
# match.end(:path) - 1]).
|
115
|
+
# Throws :error with a String message when an error is encountered.
|
116
|
+
#
|
117
|
+
# Returns nothing.
|
118
|
+
# Raises RuntimeError if the regex does not have the required named captures.
|
45
119
|
def self.import(regex, &handler)
|
120
|
+
validate_regex!(:import, regex, IMPORT_REGEX_CAPTURES)
|
121
|
+
|
46
122
|
parse(:import, regex, &handler)
|
47
123
|
end
|
48
124
|
|
49
|
-
|
50
|
-
# Configures how references are handled.
|
125
|
+
# Internal: Configure reference handling.
|
51
126
|
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
# [&handler] Block for special handling of references (optional). Should <tt>throw(:error, '...')</tt>
|
57
|
-
# on error. Passed four arguments:
|
58
|
-
# * +parse_data:+ - Hash for storing data across calls to this and other parsing handlers.
|
59
|
-
# * +match:+ - MatchData object from the match against +regex+.
|
60
|
-
# * +asset:+ - Asset object of the asset being imported.
|
61
|
-
# * +format:+ - Format of the reference (see Asset::REFERENCE_FORMATS).
|
62
|
-
# Return value is used as the substitution for the reference, with optional second and third
|
63
|
-
# values as integers representing the start and end indexes of the match to replace.
|
127
|
+
# regex - Regex for finding references. Must contain named components :quote (' or "), :path (the path
|
128
|
+
# of the asset being referenced), :quoted (everything inside the quotes), :entity ('path' or
|
129
|
+
# 'content'), and :format (see Asset::REFERENCE_FORMATS).
|
130
|
+
# handler - Proc for special handling of references (optional), which is passed four keyword arguments:
|
64
131
|
#
|
132
|
+
# parse_data: - Hash for storing arbitrary data across calls to this and other handlers.
|
133
|
+
# match: - MatchData object from the match against the regex.
|
134
|
+
# asset: - Asset object of the asset being referenced.
|
135
|
+
# format: - String format of the reference (see Asset::REFERENCE_FORMATS).
|
136
|
+
#
|
137
|
+
# Returns nil for default behavior, or a String which is used as the substitution for the text
|
138
|
+
# matched by the regex. The portion of the matched text that is replaced can optionally be
|
139
|
+
# changed by returning second and third Integer values specifying start and end indexes
|
140
|
+
# within the regex match (e.g. ['my substitution', match.begin(:path) + 1,
|
141
|
+
# match.end(:path) - 1]).
|
142
|
+
# Throws :error with a String message when an error is encountered.
|
143
|
+
#
|
144
|
+
# Returns nothing.
|
145
|
+
# Raises RuntimeError if the regex does not have the required named captures.
|
65
146
|
def self.reference(regex, &handler)
|
147
|
+
validate_regex!(:reference, regex, REFERENCE_REGEX_CAPTURES)
|
148
|
+
|
66
149
|
parse(:reference, regex, &handler)
|
67
150
|
end
|
68
151
|
|
69
|
-
|
70
|
-
#
|
152
|
+
# Internal: Configure a parser.
|
153
|
+
#
|
154
|
+
# kind - Symbol name to describe what is being parsed. Should be unique across all parse calls. When
|
155
|
+
# subclassing another Delegate, this can be used to override the parent class's regex and
|
156
|
+
# handler.
|
157
|
+
# regex - Regexp to match against.
|
158
|
+
# handler - Proc for handling matches of the regex, which is passed two keyword arguments:
|
71
159
|
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
# [regex] Regex to match against.
|
75
|
-
# [&handler] Block for handling matches of the regex. Should <tt>throw(:error, '...')</tt>
|
76
|
-
# on error. Passed two arguments:
|
77
|
-
# * +parse_data:+ - Hash for storing data across calls to this and other parsing handlers.
|
78
|
-
# * +match:+ - MatchData object from the match against +regex+.
|
79
|
-
# Return value is used as the substitution for the reference, with optional second and third
|
80
|
-
# values as integers representing the start and end indexes of the match to replace.
|
160
|
+
# parse_data: - Hash for storing arbitrary data across calls to this and other handlers.
|
161
|
+
# match: - MatchData object from the match against the regex.
|
81
162
|
#
|
163
|
+
# Returns a String which is used as the substitution for the text matched by the regex. The
|
164
|
+
# portion of the matched text that is replaced can optionally be changed by returning second
|
165
|
+
# and third Integer values specifying start and end indexes within the regex match (e.g.
|
166
|
+
# ['my substitution', match.begin(:path) + 1, match.end(:path) - 1]).
|
167
|
+
# Throws :error with a String message when an error is encountered.
|
168
|
+
#
|
169
|
+
# Returns nothing.
|
82
170
|
def self.parse(kind, regex, &handler)
|
83
|
-
@parsers
|
171
|
+
@parsers ||= parsers&.dup || {}
|
84
172
|
@parsers[kind] = [regex, handler]
|
85
173
|
end
|
86
174
|
|
87
|
-
|
88
|
-
#
|
175
|
+
# Internal: Configure compilation.
|
176
|
+
#
|
177
|
+
# lib: - String name of a library to require that is needed by the handler (optional).
|
178
|
+
# delegate: - Delegate class to be used after the asset is compiled (optional).
|
179
|
+
# handler - Proc to call that will return the compiled version of the asset's own content, which is
|
180
|
+
# passed three keyword arguments:
|
89
181
|
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
# three arguments when called:
|
94
|
-
#. * +parse_data:+ - Hash of data collected during parsing.
|
95
|
-
# * +path+ - Path of the asset being compiled.
|
96
|
-
# * +own_content+ - Asset's own content.
|
97
|
-
# Asset's own content is set to the value returned.
|
182
|
+
# parse_data: - Hash for storing arbitrary data across calls to this and other handlers.
|
183
|
+
# path: - String path of the asset.
|
184
|
+
# own_content: - String own content (without imports) of the asset.
|
98
185
|
#
|
186
|
+
# Returns a String which is used as a replacement for the asset's own content.
|
187
|
+
# Raises StandardError when an error is encountered.
|
188
|
+
#
|
189
|
+
# Returns nothing.
|
99
190
|
def self.compile(lib: nil, delegate: nil, &handler)
|
100
191
|
@compile_lib = lib
|
101
192
|
@compile_delegate = delegate
|
102
193
|
@compile_handler = handler
|
103
194
|
end
|
104
195
|
|
105
|
-
|
106
|
-
#
|
196
|
+
# Internal: Configure finalize behavior.
|
197
|
+
#
|
198
|
+
# lib: - String name of a library to require that is needed by the handler (optional).
|
199
|
+
# handler - Proc to call that will return the finalized version of the asset's compiled content (with
|
200
|
+
# imports prepended), which is passed three keyword arguments:
|
107
201
|
#
|
108
|
-
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#. * +parse_data:+ - Hash of data collected during parsing.
|
112
|
-
# * +path+ - Path of the asset being finalized.
|
113
|
-
# * +content+ - Asset's content (with imports prepended).
|
114
|
-
# Asset's content is set to the value returned.
|
202
|
+
# parse_data: - Hash for storing arbitrary data across calls to this and other handlers.
|
203
|
+
# path: - String path of the asset.
|
204
|
+
# content: - String content of the compiled asset (with imports prepended).
|
115
205
|
#
|
206
|
+
# Returns a String which is used as a replacement for the asset's content.
|
207
|
+
# Raises StandardError when an error is encountered.
|
208
|
+
#
|
209
|
+
# Returns nothing.
|
116
210
|
def self.finalize(lib: nil, &handler)
|
117
211
|
@finalize_lib = lib
|
118
212
|
@finalize_handler = handler
|
119
213
|
end
|
120
214
|
|
121
|
-
|
122
|
-
#
|
215
|
+
# Internal: Configure minification.
|
216
|
+
#
|
217
|
+
# lib: - String name of a library to require that is needed by the handler (optional).
|
218
|
+
# handler - Proc to call that will return the minified version of the asset's finalized content, which
|
219
|
+
# is passed three keyword arguments:
|
123
220
|
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
|
128
|
-
#
|
129
|
-
#
|
130
|
-
# Asset's minified content is set to the value returned.
|
221
|
+
# parse_data: - Hash for storing arbitrary data across calls to this and other handlers.
|
222
|
+
# path: - String oath of the asset being minified.
|
223
|
+
# content: - string content of the finalized asset.
|
224
|
+
#
|
225
|
+
# Returns a String which is used as the minified version of the asset's content.
|
226
|
+
# Raises StandardError when an error is encountered.
|
131
227
|
#
|
132
228
|
def self.minify(lib: nil, &handler)
|
133
229
|
@minify_lib = lib
|
134
230
|
@minify_handler = handler
|
135
231
|
end
|
136
232
|
|
137
|
-
|
138
|
-
# Throws +:error+ with a message.
|
233
|
+
# Internal: Throw :error with a message.
|
139
234
|
#
|
140
|
-
#
|
235
|
+
# message - String message to include with the throw.
|
141
236
|
#
|
237
|
+
# Returns nothing.
|
142
238
|
def self.error(message)
|
143
239
|
throw(:error, message)
|
144
240
|
end
|
145
241
|
|
146
|
-
|
147
|
-
# Returns regex for a parser.
|
242
|
+
# Internal: Get a parser's regex.
|
148
243
|
#
|
149
|
-
#
|
244
|
+
# kind - Symbol name of the parser.
|
150
245
|
#
|
246
|
+
# Returns the Regexp.
|
151
247
|
def self.regex(kind)
|
152
248
|
parsers[kind]&.first
|
153
249
|
end
|
154
250
|
|
155
|
-
|
156
|
-
# Returns handler for a parser.
|
251
|
+
# Internal: Get a parser's handler.
|
157
252
|
#
|
158
|
-
#
|
253
|
+
# kind - Symbol name of the parser.
|
159
254
|
#
|
255
|
+
# Returns the Proc handler.
|
160
256
|
def self.handler(kind)
|
161
257
|
parsers[kind]&.last
|
162
258
|
end
|
163
259
|
|
164
|
-
|
165
|
-
# Iterates over each parser and yields its kind, regex, and handler.
|
166
|
-
#
|
167
|
-
def self.each_parser
|
168
|
-
parsers&.each do |kind, (regex, handler)|
|
169
|
-
yield(kind, regex, handler)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
##
|
174
|
-
# DEPRECATED: subclass Delegate and use its DSL instead. Returns a subclass of Delegate configured using
|
175
|
-
# the supplied Hash.
|
260
|
+
# Internal: Raise an exception if a regex does not have the required named captures.
|
176
261
|
#
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
deprecated_from_hash(**params)
|
182
|
-
end
|
183
|
-
|
184
|
-
##
|
185
|
-
# DEPRECATED: subclass Delegate and use its DSL instead. Returns a subclass of Delegate configured using
|
186
|
-
# the supplied Hash.
|
262
|
+
# name - Symbol name of the regex (used in the exception message).
|
263
|
+
# regex - Regexp to validate.
|
264
|
+
# required_captures - Array of String required named captures.
|
187
265
|
#
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
self.content_type(content_type)
|
193
|
-
|
194
|
-
@import_regex = import_regex
|
195
|
-
@reference_regex = reference_regex
|
196
|
-
|
197
|
-
self.import(import_regex) if import_regex
|
198
|
-
|
199
|
-
if validate_reference || reference_content
|
200
|
-
@validate_reference = validate_reference
|
201
|
-
@reference_content = reference_content
|
266
|
+
# Returns nothing.
|
267
|
+
# Raises RuntimeError if the regex does not have the required named captures.
|
268
|
+
def self.validate_regex!(name, regex, required_captures)
|
269
|
+
missing = (required_captures - regex.named_captures.keys)
|
202
270
|
|
203
|
-
|
204
|
-
error_message = validate_reference&.call(asset, match, format)
|
205
|
-
error(error_message) if error_message
|
271
|
+
return if missing.empty?
|
206
272
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
self.reference(reference_regex)
|
211
|
-
end
|
273
|
+
name = name.to_s.capitalize
|
274
|
+
plural = missing.size != 1
|
275
|
+
missing_str = missing.join(', ')
|
212
276
|
|
213
|
-
|
214
|
-
self.compile(lib: compile_lib, delegate: compiled) do |parse_data:, path:, own_content:|
|
215
|
-
compile.call(path, own_content)
|
216
|
-
end
|
217
|
-
elsif compile_lib || compiled
|
218
|
-
self.compile(lib: compile_lib, delegate: compiled)
|
219
|
-
end
|
220
|
-
|
221
|
-
if minify
|
222
|
-
self.minify(lib: minify_lib) do |parse_data:, path:, content:|
|
223
|
-
minify.call(content)
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
277
|
+
raise("#{name} regex is missing required named capture#{'s' if plural}: #{missing_str}")
|
227
278
|
end
|
228
|
-
|
229
|
-
##
|
230
|
-
# DEPRECATED: subclass Delegate and use its DSL instead.
|
231
|
-
#
|
232
|
-
def self.import_regex() @import_regex end
|
233
|
-
def self.reference_regex() @reference_regex end
|
234
|
-
def self.validate_reference() @validate_reference end
|
235
|
-
def self.reference_content() @reference_content end
|
236
279
|
end
|
237
280
|
end
|
@@ -4,6 +4,7 @@ require_relative('../asset')
|
|
4
4
|
require_relative('../delegate')
|
5
5
|
|
6
6
|
class Darkroom
|
7
|
+
# Delegate for handling HTML-specific asset processing.
|
7
8
|
class HTMLDelegate < Delegate
|
8
9
|
REFERENCE_REGEX = /
|
9
10
|
<(?<tag>a|area|audio|base|embed|iframe|img|input|link|script|source|track|video)\s+[^>]*
|
@@ -26,8 +27,8 @@ class Darkroom
|
|
26
27
|
if asset.content_type == 'text/javascript'
|
27
28
|
offset = match.begin(0)
|
28
29
|
|
29
|
-
"#{match[0][0..(match.begin(:attr) - 2 - offset)]}"\
|
30
|
-
"#{match[0][(match.end(:quoted) + match[:quote].size - offset)..(match.end(0) - offset)]}"\
|
30
|
+
"#{match[0][0..(match.begin(:attr) - 2 - offset)]}" \
|
31
|
+
"#{match[0][(match.end(:quoted) + match[:quote].size - offset)..(match.end(0) - offset)]}" \
|
31
32
|
"#{asset.content}"
|
32
33
|
else
|
33
34
|
error('Asset content type must be text/javascript')
|
@@ -46,7 +47,7 @@ class Darkroom
|
|
46
47
|
|
47
48
|
content = asset.content.dup
|
48
49
|
content.gsub!('#', '%23')
|
49
|
-
content.gsub!(quote, quote == '"' ?
|
50
|
+
content.gsub!(quote, quote == '"' ? '"' : ''')
|
50
51
|
|
51
52
|
content
|
52
53
|
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative('
|
4
|
-
require_relative('
|
3
|
+
require_relative('html_delegate')
|
4
|
+
require_relative('javascript_delegate')
|
5
5
|
|
6
6
|
class Darkroom
|
7
|
+
# Delegate for handling HTX-specific asset processing.
|
7
8
|
class HTXDelegate < HTMLDelegate
|
8
9
|
compile(lib: 'htx', delegate: JavaScriptDelegate) do |parse_data:, path:, own_content:|
|
9
10
|
module_supported = false
|
@@ -5,13 +5,14 @@ require_relative('../asset')
|
|
5
5
|
require_relative('../delegate')
|
6
6
|
|
7
7
|
class Darkroom
|
8
|
+
# Delegate for handling JavaScript-specific asset processing.
|
8
9
|
class JavaScriptDelegate < Delegate
|
9
10
|
IDENTIFIER_REGEX = /[_$a-zA-Z][_$a-zA-Z0-9]*/.freeze
|
10
11
|
COMMA_REGEX = /,/.freeze
|
11
12
|
QUOTED_REGEX = /
|
12
13
|
(?<quoted>
|
13
|
-
(?<quote>['"])(
|
14
|
-
(?<=[^\\])\\(
|
14
|
+
(?<quote>['"])(?:
|
15
|
+
(?<=[^\\])\\(?:\\\\)*\k<quote> |
|
15
16
|
(?!\k<quote>).
|
16
17
|
)*\k<quote>
|
17
18
|
)
|
@@ -131,14 +132,14 @@ class Darkroom
|
|
131
132
|
end while items.any? { |i| i.first == mod }
|
132
133
|
|
133
134
|
own_content.prepend(
|
134
|
-
"let #{items.map(&:first).join(', ')}; "\
|
135
|
-
"$import('#{import_path}', "\
|
135
|
+
"let #{items.map(&:first).join(', ')}; " \
|
136
|
+
"$import('#{import_path}', " \
|
136
137
|
"#{mod} => #{prefix}#{items.map { |(i, e)| "#{i} = #{mod}#{e}" }.join(', ')}#{suffix})\n"
|
137
138
|
)
|
138
139
|
end
|
139
140
|
|
140
141
|
own_content.prepend("['#{path}', $import => {\n\n")
|
141
|
-
own_content << <<~
|
142
|
+
own_content << <<~JS
|
142
143
|
|
143
144
|
return Object.seal({#{
|
144
145
|
if parse_data[:exports] && !parse_data[:exports].empty?
|
@@ -147,7 +148,7 @@ class Darkroom
|
|
147
148
|
}})
|
148
149
|
|
149
150
|
}],
|
150
|
-
|
151
|
+
JS
|
151
152
|
end
|
152
153
|
|
153
154
|
########################################################################################################
|
@@ -158,7 +159,7 @@ class Darkroom
|
|
158
159
|
next unless Darkroom.javascript_iife
|
159
160
|
|
160
161
|
(content.frozen? ? content.dup : content).prepend(
|
161
|
-
<<~
|
162
|
+
<<~JS
|
162
163
|
((...bundle) => {
|
163
164
|
const modules = {}
|
164
165
|
const setters = []
|
@@ -172,7 +173,7 @@ class Darkroom
|
|
172
173
|
setter(modules[name])
|
173
174
|
})(
|
174
175
|
|
175
|
-
|
176
|
+
JS
|
176
177
|
) << "\n)\n"
|
177
178
|
end
|
178
179
|
|
@@ -1,33 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Darkroom
|
4
|
-
##
|
5
4
|
# General error class used for errors encountered while processing an asset.
|
6
|
-
#
|
7
5
|
class AssetError < StandardError
|
8
6
|
attr_reader(:detail, :source_path, :source_line_num)
|
9
7
|
|
10
|
-
|
11
|
-
# Creates a new instance.
|
12
|
-
#
|
13
|
-
# [message] Description of the error.
|
14
|
-
# [detail] Additional detail about the error.
|
15
|
-
# [source_path] Path of the asset that contains the error.
|
16
|
-
# [source_line_num] Line number in the asset where the error is located.
|
8
|
+
# Public: Create a new instance.
|
17
9
|
#
|
10
|
+
# message - String description of the error.
|
11
|
+
# detail - String additional error detail.
|
12
|
+
# source_path - String path of the asset that contains the error.
|
13
|
+
# source_line_num - Integer line number in the asset file where the error was located.
|
18
14
|
def initialize(message, detail, source_path = nil, source_line_num = nil)
|
19
|
-
super(message)
|
15
|
+
super("#{"#{source_path}:#{source_line_num || '?'}: " if source_path}#{message}: #{detail}")
|
20
16
|
|
21
17
|
@detail = detail
|
22
18
|
@source_path = source_path
|
23
19
|
@source_line_num = source_line_num
|
24
20
|
end
|
25
|
-
|
26
|
-
##
|
27
|
-
# Returns a string representation of the error.
|
28
|
-
#
|
29
|
-
def to_s
|
30
|
-
"#{"#{@source_path}:#{@source_line_num || '?'}: " if @source_path}#{super}: #{@detail}"
|
31
|
-
end
|
32
21
|
end
|
33
22
|
end
|
@@ -3,18 +3,14 @@
|
|
3
3
|
require_relative('asset_error')
|
4
4
|
|
5
5
|
class Darkroom
|
6
|
-
##
|
7
6
|
# Error class used when an asset requested explicitly or specified as a dependency of another doesn't
|
8
7
|
# exist.
|
9
|
-
#
|
10
8
|
class AssetNotFoundError < AssetError
|
11
|
-
|
12
|
-
# Creates a new instance.
|
13
|
-
#
|
14
|
-
# [path] Path of asset that doesn't exist.
|
15
|
-
# [source_path] Path of the asset that contains the error.
|
16
|
-
# [source_line_num] Line number in the asset where the error is located.
|
9
|
+
# Public: Create a new instance.
|
17
10
|
#
|
11
|
+
# path - String path of asset that doesn't exist.
|
12
|
+
# source_path - String path of the asset that contains the error.
|
13
|
+
# source_line_num - Integer line number in the asset file where the error is located.
|
18
14
|
def initialize(path, source_path = nil, source_line_num = nil)
|
19
15
|
super('Asset not found', path, source_path, source_line_num)
|
20
16
|
end
|
@@ -3,17 +3,13 @@
|
|
3
3
|
require_relative('asset_error')
|
4
4
|
|
5
5
|
class Darkroom
|
6
|
-
##
|
7
6
|
# Error class used when an asset reference results in a circular reference chain.
|
8
|
-
#
|
9
7
|
class CircularReferenceError < AssetError
|
10
|
-
|
11
|
-
# Creates a new instance.
|
12
|
-
#
|
13
|
-
# [snippet] Snippet showing the reference.
|
14
|
-
# [source_path] Path of the asset that contains the error.
|
15
|
-
# [source_line_num] Line number in the asset where the error is located.
|
8
|
+
# Public: Create a new instance.
|
16
9
|
#
|
10
|
+
# snippet - String snippet showing the reference.
|
11
|
+
# source_path - String path of the asset that contains the error.
|
12
|
+
# source_line_num - Integer line number in the asset file where the error is located.
|
17
13
|
def initialize(snippet, source_path, source_line_num)
|
18
14
|
super('Reference would result in a circular reference chain', snippet, source_path, source_line_num)
|
19
15
|
end
|