json-ld 0.0.8 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.markdown +36 -0
- data/{README → README.markdown} +1 -1
- data/VERSION +1 -1
- data/lib/json/ld.rb +92 -16
- data/lib/json/ld/api.rb +320 -0
- data/lib/json/ld/evaluation_context.rb +640 -0
- data/lib/json/ld/extensions.rb +6 -0
- data/lib/json/ld/reader.rb +120 -270
- data/lib/json/ld/writer.rb +210 -284
- metadata +53 -38
data/lib/json/ld/extensions.rb
CHANGED
data/lib/json/ld/reader.rb
CHANGED
@@ -15,84 +15,6 @@ module JSON::LD
|
|
15
15
|
# @return [RDF::Graph]
|
16
16
|
attr_reader :graph
|
17
17
|
|
18
|
-
##
|
19
|
-
# Context
|
20
|
-
#
|
21
|
-
# The `@context` keyword is used to change how the JSON-LD processor evaluates key- value pairs. In this
|
22
|
-
# case, it was used to map one string (`'myvocab'`) to another string, which is interpreted as a IRI. In the
|
23
|
-
# example above, the `myvocab` string is replaced with "http://example.org/myvocab#" when it is detected. In
|
24
|
-
# the example above, `"myvocab:personality"` would expand to "http://example.org/myvocab#personality".
|
25
|
-
#
|
26
|
-
# This mechanism is a short-hand for RDF, called a `CURIE`, and provides developers an unambiguous way to
|
27
|
-
# map any JSON value to RDF.
|
28
|
-
#
|
29
|
-
# @private
|
30
|
-
class EvaluationContext # :nodoc:
|
31
|
-
# The base.
|
32
|
-
#
|
33
|
-
# The `@base` string is a special keyword that states that any relative IRI MUST be appended to the string
|
34
|
-
# specified by `@base`.
|
35
|
-
#
|
36
|
-
# @attr [RDF::URI]
|
37
|
-
attr :base, true
|
38
|
-
|
39
|
-
# A list of current, in-scope URI mappings.
|
40
|
-
#
|
41
|
-
# @attr [Hash{String => String}]
|
42
|
-
attr :mappings, true
|
43
|
-
|
44
|
-
# The default vocabulary
|
45
|
-
#
|
46
|
-
# A value to use as the prefix URI when a term is used.
|
47
|
-
# This specification does not define an initial setting for the default vocabulary.
|
48
|
-
# Host Languages may define an initial setting.
|
49
|
-
#
|
50
|
-
# @attr [String]
|
51
|
-
attr :vocab, true
|
52
|
-
|
53
|
-
# Type coersion
|
54
|
-
#
|
55
|
-
# The @coerce keyword is used to specify type coersion rules for the data. For each key in the map, the
|
56
|
-
# key is the type to be coerced to and the value is the vocabulary term to be coerced. Type coersion for
|
57
|
-
# the key `@iri` asserts that all vocabulary terms listed should undergo coercion to an IRI,
|
58
|
-
# including `@base` processing for relative IRIs and CURIE processing for compact URI Expressions like
|
59
|
-
# `foaf:homepage`.
|
60
|
-
#
|
61
|
-
# As the value may be an array, this is maintained as a reverse mapping of `property` => `type`.
|
62
|
-
#
|
63
|
-
# @attr [Hash{String => String}]
|
64
|
-
attr :coerce
|
65
|
-
|
66
|
-
# List coercion
|
67
|
-
#
|
68
|
-
# The @list keyword is used to specify that properties having an array value are to be treated
|
69
|
-
# as an ordered list, rather than a normal unordered list
|
70
|
-
# @attr [Array<String>]
|
71
|
-
attr :list
|
72
|
-
|
73
|
-
##
|
74
|
-
# Create new evaluation context
|
75
|
-
# @yield [ec]
|
76
|
-
# @yieldparam [EvaluationContext]
|
77
|
-
# @return [EvaluationContext]
|
78
|
-
def initialize
|
79
|
-
@base = nil
|
80
|
-
@mappings = {}
|
81
|
-
@vocab = nil
|
82
|
-
@coerce = {}
|
83
|
-
@list = []
|
84
|
-
yield(self) if block_given?
|
85
|
-
end
|
86
|
-
|
87
|
-
def inspect
|
88
|
-
v = %w([EvaluationContext) + %w(base vocab).map {|a| "#{a}='#{self.send(a).inspect}'"}
|
89
|
-
v << "mappings[#{mappings.keys.length}]=#{mappings}"
|
90
|
-
v << "coerce[#{coerce.keys.length}]=#{coerce}"
|
91
|
-
v << "list[#{list.length}]=#{list}"
|
92
|
-
v.join(", ") + "]"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
18
|
##
|
97
19
|
# Initializes the RDF/JSON reader instance.
|
98
20
|
#
|
@@ -105,7 +27,6 @@ module JSON::LD
|
|
105
27
|
# @raise [RDF::ReaderError] if the JSON document cannot be loaded
|
106
28
|
def initialize(input = $stdin, options = {}, &block)
|
107
29
|
super do
|
108
|
-
@base_uri = uri(options[:base_uri]) if options[:base_uri]
|
109
30
|
begin
|
110
31
|
@doc = JSON.load(input)
|
111
32
|
rescue JSON::ParserError => e
|
@@ -128,11 +49,8 @@ module JSON::LD
|
|
128
49
|
def each_statement(&block)
|
129
50
|
@callback = block
|
130
51
|
|
131
|
-
# initialize the evaluation context with
|
132
|
-
ec = EvaluationContext.new
|
133
|
-
e.base = @base_uri if @base_uri
|
134
|
-
parse_context(e, DEFAULT_CONTEXT)
|
135
|
-
end
|
52
|
+
# initialize the evaluation context with initial context
|
53
|
+
ec = EvaluationContext.new(@options)
|
136
54
|
|
137
55
|
traverse("", @doc, nil, nil, ec)
|
138
56
|
end
|
@@ -159,206 +77,140 @@ module JSON::LD
|
|
159
77
|
# Inherited property
|
160
78
|
# @param [EvaluationContext] ec
|
161
79
|
# The active context
|
80
|
+
# @return [RDF::Resource] defined by this element
|
81
|
+
# @yield :resource
|
82
|
+
# @yieldparam [RDF::Resource] :resource
|
162
83
|
def traverse(path, element, subject, property, ec)
|
163
|
-
|
164
|
-
object = nil
|
84
|
+
debug(path) {"traverse: e=#{element.class.inspect}, s=#{subject.inspect}, p=#{property.inspect}, e=#{ec.inspect}"}
|
165
85
|
|
166
|
-
case element
|
86
|
+
traverse_result = case element
|
167
87
|
when Hash
|
168
|
-
# 2) ... For each key-value
|
169
|
-
# pair in the associative array, using the newly created processor state do the
|
170
|
-
# following:
|
171
|
-
|
172
88
|
# 2.1) If a @context keyword is found, the processor merges each key-value pair in
|
173
89
|
# the local context into the active context ...
|
174
90
|
if element['@context']
|
175
91
|
# Merge context
|
176
|
-
ec =
|
92
|
+
ec = ec.parse(element['@context'])
|
177
93
|
prefixes.merge!(ec.mappings) # Update parsed prefixes
|
178
94
|
end
|
179
95
|
|
180
|
-
# 2.2) Create a
|
96
|
+
# 2.2) Create a copy of the current JSON object, changing keys that map to JSON-LD keywords with those keywords.
|
97
|
+
# Use the new JSON object in subsequent steps
|
181
98
|
new_element = {}
|
182
99
|
element.each do |k, v|
|
183
|
-
k = ec.
|
100
|
+
k = ec.mapping(k) if ec.mapping(k).to_s[0,1] == '@'
|
184
101
|
new_element[k] = v
|
185
102
|
end
|
186
103
|
unless element == new_element
|
187
|
-
|
104
|
+
debug(path) {"traverse: keys after map: #{new_element.keys.inspect}"}
|
188
105
|
element = new_element
|
189
106
|
end
|
190
107
|
|
191
108
|
# Other shortcuts to allow use of this method for terminal associative arrays
|
192
|
-
if element['@
|
193
|
-
# 2.3
|
194
|
-
object = expand_term(element['@iri'], ec.base, ec)
|
195
|
-
add_triple(path, subject, property, object) if subject && property
|
196
|
-
return
|
197
|
-
elsif element['@literal']
|
198
|
-
# 2.4
|
109
|
+
object = if element['@literal']
|
110
|
+
# 2.3) If the JSON object has a @literal key, set the active object to a literal value as follows ...
|
199
111
|
literal_opts = {}
|
200
|
-
literal_opts[:datatype] =
|
112
|
+
literal_opts[:datatype] = ec.expand_iri(element['@type'], :position => :datatype) if element['@type']
|
201
113
|
literal_opts[:language] = element['@language'].to_sym if element['@language']
|
202
|
-
|
203
|
-
add_triple(path, subject, property, object) if subject && property
|
204
|
-
return
|
114
|
+
RDF::Literal.new(element['@literal'], literal_opts)
|
205
115
|
elsif element['@list']
|
206
|
-
# 2.
|
207
|
-
parse_list("#{path}[#{'@list'}]", element['@list'],
|
208
|
-
|
209
|
-
|
116
|
+
# 2.4 (Lists)
|
117
|
+
parse_list("#{path}[#{'@list'}]", element['@list'], property, ec) do |resource|
|
118
|
+
add_triple(path, subject, property, resource) if subject && property
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
if object
|
123
|
+
yield object if block_given?
|
124
|
+
return object
|
125
|
+
end
|
126
|
+
|
127
|
+
active_subject = if element['@id'].is_a?(String)
|
210
128
|
# 2.5 Subject
|
211
129
|
# 2.5.1 Set active object (subject)
|
212
|
-
|
213
|
-
elsif element['@
|
130
|
+
ec.expand_iri(element['@id'], :position => :subject)
|
131
|
+
elsif element['@id']
|
214
132
|
# 2.5.2 Recursively process hash or Array values
|
215
|
-
traverse("#{path}[#{'@
|
133
|
+
traverse("#{path}[#{'@id'}]", element['@id'], subject, property, ec) do |resource|
|
134
|
+
add_triple(path, subject, property, resource) if subject && property
|
135
|
+
end
|
216
136
|
else
|
217
137
|
# 2.6) Generate a blank node identifier and set it as the active subject.
|
218
|
-
|
138
|
+
RDF::Node.new
|
219
139
|
end
|
220
140
|
|
221
|
-
add_triple(path, subject, property, active_subject) if subject && property
|
222
141
|
subject = active_subject
|
223
142
|
|
143
|
+
# 2.7) For each key in the JSON object that has not already been processed, perform the following steps:
|
224
144
|
element.each do |key, value|
|
225
|
-
# 2.7) If a key that is not @context, @
|
145
|
+
# 2.7.1) If a key that is not @context, @id, or @type, set the active property by
|
226
146
|
# performing Property Processing on the key.
|
227
147
|
property = case key
|
228
|
-
when '@type' then
|
148
|
+
when '@type' then RDF.type
|
229
149
|
when /^@/ then next
|
230
|
-
else
|
150
|
+
else ec.expand_iri(key, :position => :predicate)
|
231
151
|
end
|
232
152
|
|
233
|
-
# 2.7.3
|
234
|
-
if ec.list
|
235
|
-
#
|
236
|
-
#
|
237
|
-
parse_list("#{path}[#{key}]", value,
|
153
|
+
# 2.7.3) List expansion
|
154
|
+
object = if ec.list(property) && value.is_a?(Array)
|
155
|
+
# If the active property is the target of a @list coercion, and the value is an array,
|
156
|
+
# process the value as a list starting at Step 3.1.
|
157
|
+
parse_list("#{path}[#{key}]", value, property, ec) do |resource|
|
158
|
+
# Adds triple for head BNode only, the rest of the list is done within the method
|
159
|
+
add_triple(path, subject, property, resource) if subject && property
|
160
|
+
end
|
238
161
|
else
|
239
|
-
traverse("#{path}[#{key}]", value, subject, property, ec)
|
162
|
+
traverse("#{path}[#{key}]", value, subject, property, ec) do |resource|
|
163
|
+
# Adds triples for each value
|
164
|
+
add_triple(path, subject, property, resource) if subject && property
|
165
|
+
end
|
240
166
|
end
|
241
167
|
end
|
168
|
+
|
169
|
+
# 2.8) The subject is returned
|
170
|
+
subject
|
242
171
|
when Array
|
243
|
-
# 3) If a regular array is detected
|
172
|
+
# 3) If a regular array is detected ...
|
244
173
|
element.each_with_index do |v, i|
|
245
|
-
traverse("#{path}[#{i}]", v, subject, property, ec)
|
174
|
+
traverse("#{path}[#{i}]", v, subject, property, ec) do |resource|
|
175
|
+
add_triple(path, subject, property, resource) if subject && property
|
176
|
+
end
|
246
177
|
end
|
178
|
+
nil # No real value returned from an array
|
247
179
|
when String
|
248
|
-
# Perform coersion of the value, or generate a literal
|
249
|
-
|
250
|
-
"traverse(#{element}): coerce
|
251
|
-
"ec=#{ec.
|
180
|
+
# 4) Perform coersion of the value, or generate a literal
|
181
|
+
debug(path) do
|
182
|
+
"traverse(#{element}): coerce(#{property.inspect}) == #{ec.coerce(property).inspect}, " +
|
183
|
+
"ec=#{ec.coercions.inspect}"
|
252
184
|
end
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
185
|
+
if ec.coerce(property) == '@id'
|
186
|
+
# 4.1) If the active property is the target of a @id coercion ...
|
187
|
+
ec.expand_iri(element, :position => :object)
|
188
|
+
elsif ec.coerce(property)
|
189
|
+
# 4.2) Otherwise, if the active property is the target of coercion ..
|
190
|
+
RDF::Literal.new(element, :datatype => ec.coerce(property))
|
257
191
|
else
|
258
|
-
|
192
|
+
# 4.3) Otherwise, set the active object to a plain literal value created from the string.
|
193
|
+
RDF::Literal.new(element, :language => ec.language)
|
259
194
|
end
|
260
|
-
property = RDF.type if property == '@type'
|
261
|
-
add_triple(path, subject, property, object) if subject && property
|
262
195
|
when Float
|
263
196
|
object = RDF::Literal::Double.new(element)
|
264
|
-
|
265
|
-
|
197
|
+
debug(path) {"traverse(#{element}): native: #{object.inspect}"}
|
198
|
+
object
|
266
199
|
when Fixnum
|
267
200
|
object = RDF::Literal.new(element)
|
268
|
-
|
269
|
-
|
201
|
+
debug(path) {"traverse(#{element}): native: #{object.inspect}"}
|
202
|
+
object
|
270
203
|
when TrueClass, FalseClass
|
271
204
|
object = RDF::Literal::Boolean.new(element)
|
272
|
-
|
273
|
-
|
205
|
+
debug(path) {"traverse(#{element}): native: #{object.inspect}"}
|
206
|
+
object
|
274
207
|
else
|
275
208
|
raise RDF::ReaderError, "Traverse to unknown element: #{element.inspect} of type #{element.class}"
|
276
209
|
end
|
277
|
-
end
|
278
|
-
|
279
|
-
##
|
280
|
-
# add a statement, object can be literal or URI or bnode
|
281
|
-
#
|
282
|
-
# @param [String] path
|
283
|
-
# @param [URI, BNode] subject the subject of the statement
|
284
|
-
# @param [URI] predicate the predicate of the statement
|
285
|
-
# @param [URI, BNode, Literal] object the object of the statement
|
286
|
-
# @return [Statement] Added statement
|
287
|
-
# @raise [ReaderError] Checks parameter types and raises if they are incorrect if parsing mode is _validate_.
|
288
|
-
def add_triple(path, subject, predicate, object)
|
289
|
-
statement = RDF::Statement.new(subject, predicate, object)
|
290
|
-
add_debug(path) {"statement: #{statement.to_ntriples}"}
|
291
|
-
@callback.call(statement)
|
292
|
-
end
|
293
|
-
|
294
|
-
##
|
295
|
-
# Add debug event to debug array, if specified
|
296
|
-
#
|
297
|
-
# @param [XML Node, any] node:: XML Node or string for showing context
|
298
|
-
# @param [String] message
|
299
|
-
# @yieldreturn [String] appended to message, to allow for lazy-evaulation of message
|
300
|
-
def add_debug(node, message = "")
|
301
|
-
return unless ::JSON::LD.debug? || @options[:debug]
|
302
|
-
message = message + yield if block_given?
|
303
|
-
puts "#{node}: #{message}" if JSON::LD::debug?
|
304
|
-
@options[:debug] << "#{node}: #{message}" if @options[:debug].is_a?(Array)
|
305
|
-
end
|
306
|
-
|
307
|
-
##
|
308
|
-
# Parse a JSON context, into a new EvaluationContext
|
309
|
-
# @param [Hash{String => String,Hash}, String] context
|
310
|
-
# JSON representation of @context
|
311
|
-
# @return [EvaluationContext]
|
312
|
-
# @raise [RDF::ReaderError]
|
313
|
-
# on a remote context load error, syntax error, or a reference to a term which is not defined.
|
314
|
-
def parse_context(ec, context)
|
315
|
-
# Load context document, if it is a string
|
316
|
-
if context.is_a?(String)
|
317
|
-
begin
|
318
|
-
context = open(context.to_s) {|f| JSON.load(f)}
|
319
|
-
rescue JSON::ParserError => e
|
320
|
-
raise RDF::ReaderError, "Failed to parse remote context at #{context}: #{e.message}"
|
321
|
-
end
|
322
|
-
end
|
323
210
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
when '@vocab' then ec.vocab = value
|
328
|
-
when '@base' then ec.base = uri(value)
|
329
|
-
when '@coerce'
|
330
|
-
# Process after prefix mapping
|
331
|
-
else
|
332
|
-
# Spec confusion: The text indicates to merge each key-value pair into the active context. Is any
|
333
|
-
# processing performed on the values. For instance, could a value be a CURIE, or {"@iri": <value>}?
|
334
|
-
# Examples indicate that there is no such processing, and each value should be an absolute IRI. The
|
335
|
-
# wording makes this unclear.
|
336
|
-
ec.mappings[key.to_s] = value
|
337
|
-
end
|
338
|
-
end
|
339
|
-
|
340
|
-
if context['@coerce']
|
341
|
-
# Spec confusion: doc says to merge each key-value mapping to the local context's @coerce mapping,
|
342
|
-
# overwriting duplicate values. In the case where a mapping is indicated to a list of properties
|
343
|
-
# (e.g., { "@iri": ["foaf:homepage", "foaf:member"] }, does this overwrite a previous mapping
|
344
|
-
# of { "@iri": "foaf:knows" }, or add to it.
|
345
|
-
add_error RDF::ReaderError, "Expected @coerce to reference an associative array" unless context['@coerce'].is_a?(Hash)
|
346
|
-
context['@coerce'].each do |type, property|
|
347
|
-
add_debug("parse_context: @coerce") {"type=#{type}, prop=#{property}"}
|
348
|
-
type_uri = expand_term(type, ec.vocab, ec).to_s
|
349
|
-
[property].flatten.compact.each do |prop|
|
350
|
-
p = expand_term(prop, ec.vocab, ec).to_s
|
351
|
-
if type == '@list'
|
352
|
-
# List is managed separate from types, as it is maintained in normal form.
|
353
|
-
ec.list << p unless ec.list.include?(p)
|
354
|
-
else
|
355
|
-
ec.coerce[p] = type_uri
|
356
|
-
end
|
357
|
-
end
|
358
|
-
end
|
359
|
-
end
|
360
|
-
|
361
|
-
ec
|
211
|
+
# Yield and return traverse_result
|
212
|
+
yield traverse_result if traverse_result && block_given?
|
213
|
+
traverse_result
|
362
214
|
end
|
363
215
|
|
364
216
|
##
|
@@ -368,71 +220,69 @@ module JSON::LD
|
|
368
220
|
# location within JSON hash
|
369
221
|
# @param [Array] list
|
370
222
|
# The Array to serialize as a list
|
371
|
-
# @param [RDF::URI] subject
|
372
|
-
# Inherited subject
|
373
223
|
# @param [RDF::URI] property
|
374
224
|
# Inherited property
|
375
225
|
# @param [EvaluationContext] ec
|
376
226
|
# The active context
|
377
|
-
|
378
|
-
|
227
|
+
# @return [RDF::Resource] BNode or nil for head of list
|
228
|
+
# @yield :resource
|
229
|
+
# BNode or nil for head of list
|
230
|
+
# @yieldparam [RDF::Resource] :resource
|
231
|
+
def parse_list(path, list, property, ec)
|
232
|
+
debug(path) {"list: #{list.inspect}, p=#{property.inspect}, e=#{ec.inspect}"}
|
379
233
|
|
380
234
|
last = list.pop
|
381
|
-
first_bnode = last ? RDF::Node.new : RDF.nil
|
382
|
-
add_triple("#{path}", subject, property, first_bnode)
|
235
|
+
result = first_bnode = last ? RDF::Node.new : RDF.nil
|
383
236
|
|
384
237
|
list.each do |list_item|
|
385
|
-
|
238
|
+
# Traverse the value, using _property_, not rdf:first, to ensure that
|
239
|
+
# proper type coercion is performed
|
240
|
+
traverse("#{path}", list_item, first_bnode, property, ec) do |resource|
|
241
|
+
add_triple("#{path}", first_bnode, RDF.first, resource)
|
242
|
+
end
|
386
243
|
rest_bnode = RDF::Node.new
|
387
244
|
add_triple("#{path}", first_bnode, RDF.rest, rest_bnode)
|
388
245
|
first_bnode = rest_bnode
|
389
246
|
end
|
390
247
|
if last
|
391
|
-
traverse("#{path}", last, first_bnode,
|
248
|
+
traverse("#{path}", last, first_bnode, property, ec) do |resource|
|
249
|
+
add_triple("#{path}", first_bnode, RDF.first, resource)
|
250
|
+
end
|
392
251
|
add_triple("#{path}", first_bnode, RDF.rest, RDF.nil)
|
393
252
|
end
|
253
|
+
|
254
|
+
yield result if block_given?
|
255
|
+
result
|
394
256
|
end
|
395
257
|
|
396
258
|
##
|
397
|
-
#
|
398
|
-
#
|
399
|
-
# @param [String] term
|
400
|
-
# @param [String] base Base to apply to URIs
|
401
|
-
# @param [EvaluationContext] ec
|
259
|
+
# add a statement, object can be literal or URI or bnode
|
402
260
|
#
|
403
|
-
# @
|
404
|
-
# @
|
405
|
-
# @
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
base.respond_to?(:join) ? base.join(term) : uri(base + term)
|
415
|
-
else
|
416
|
-
uri(term)
|
417
|
-
end
|
418
|
-
end
|
419
|
-
|
420
|
-
def uri(value, append = nil)
|
421
|
-
value = RDF::URI.new(value)
|
422
|
-
value = value.join(append) if append
|
423
|
-
value.validate! if validate?
|
424
|
-
value.canonicalize! if canonicalize?
|
425
|
-
value = RDF::URI.intern(value) if intern?
|
426
|
-
value
|
261
|
+
# @param [String] path
|
262
|
+
# @param [URI, BNode] subject the subject of the statement
|
263
|
+
# @param [URI] predicate the predicate of the statement
|
264
|
+
# @param [URI, BNode, Literal] object the object of the statement
|
265
|
+
# @return [Statement] Added statement
|
266
|
+
# @raise [ReaderError] Checks parameter types and raises if they are incorrect if parsing mode is _validate_.
|
267
|
+
def add_triple(path, subject, predicate, object)
|
268
|
+
predicate = RDF.type if predicate == '@type'
|
269
|
+
statement = RDF::Statement.new(subject, predicate, object)
|
270
|
+
debug(path) {"statement: #{statement.to_ntriples}"}
|
271
|
+
@callback.call(statement)
|
427
272
|
end
|
428
273
|
|
429
|
-
|
274
|
+
##
|
275
|
+
# Add debug event to debug array, if specified
|
430
276
|
#
|
431
|
-
#
|
432
|
-
# @
|
433
|
-
|
434
|
-
|
435
|
-
|
277
|
+
# @param [XML Node, any] node:: XML Node or string for showing context
|
278
|
+
# @param [String] message
|
279
|
+
# @yieldreturn [String] appended to message, to allow for lazy-evaulation of message
|
280
|
+
def debug(*args)
|
281
|
+
return unless ::JSON::LD.debug? || @options[:debug]
|
282
|
+
message = " " * (@depth || 0) * 2 + (args.empty? ? "" : args.join(": "))
|
283
|
+
message += yield if block_given?
|
284
|
+
puts message if JSON::LD::debug?
|
285
|
+
@options[:debug] << message if @options[:debug].is_a?(Array)
|
436
286
|
end
|
437
287
|
end
|
438
288
|
end
|