json-ld 0.0.8 → 0.1.0
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.
- 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
|