json-ld 1.1.8 → 1.1.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1f6790b14a0a5f9c477e63ad9b8788b03be1eabe
4
- data.tar.gz: 8fc23868782eb98f4c375607ff6bf01813a5aa78
3
+ metadata.gz: 3404c8ed3ac6a383038d1db06f3c2ad1a8d58135
4
+ data.tar.gz: 9818ef47ffd7b6d08eb3f387fc9be333b11aca1e
5
5
  SHA512:
6
- metadata.gz: 7134666ce6f5e0c47148c6a032e1fb13be5c272abd5db50b1a84b7925857b7a86e3f3444718cb2b0d7717eed49a4d24f70bb6a3beaa3da6b394ad68aab1c6140
7
- data.tar.gz: 88f96434d3c7b342e7be136c3b9b20ded52c93f4d8234af446e164336decc7a6b9dbd99f59d362619a8fe6f95a7855adbc8feacb929c99601e41a415a7739ded
6
+ metadata.gz: 09e34ee5537cb9c5004765c735a1fbfcc33b08b89a6d1f9386912ca006459b3582e33f90236d73074eeb1eafcba7fc87e2acb44c14ebbdeeccac50547f3bf117
7
+ data.tar.gz: 0bda2990643c9f5c4cd4c89a74f6594cc7abd6c4b6e55d8d24ece746dc3980a1b7401714aeb490c1882f214a92a81c6baf6128f92a21825c9da28d6d4a1dcf4e
data/README.md CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  [![Gem Version](https://badge.fury.io/rb/json-ld.png)](http://badge.fury.io/rb/json-ld)
6
6
  [![Build Status](https://secure.travis-ci.org/ruby-rdf/json-ld.png?branch=master)](http://travis-ci.org/ruby-rdf/json-ld)
7
+ [![Coverage Status](https://coveralls.io/repos/ruby-rdf/json-ld/badge.svg)](https://coveralls.io/r/ruby-rdf/json-ld)
7
8
 
8
9
  ## Features
9
10
 
@@ -11,6 +12,8 @@ JSON::LD parses and serializes [JSON-LD][] into [RDF][] and implements expansion
11
12
 
12
13
  JSON::LD can now be used to create a _context_ from an RDFS/OWL definition, and optionally include a JSON-LD representation of the ontology itself. This is currently accessed through the `script/gen_context` script.
13
14
 
15
+ If the [jsonlint][] gem is installed, it will be used when validating an input document.
16
+
14
17
  Install with `gem install json-ld`
15
18
 
16
19
  ### JSON-LD Streaming Profile
@@ -301,3 +304,4 @@ see <http://unlicense.org/> or the accompanying {file:UNLICENSE} file.
301
304
  [JSON-LD API]: http://www.w3.org/TR/json-ld-api/ "JSON-LD 1.0 Processing Algorithms and API"
302
305
  [JSON-LD Framing]: http://json-ld.org/spec/latest/json-ld-framing/ "JSON-LD Framing 1.0"
303
306
  [Promises]: http://dom.spec.whatwg.org/#promises
307
+ [jsonlint]: https://rubygems.org/gems/jsonlint
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.8
1
+ 1.1.9
@@ -6,6 +6,11 @@ require 'json/ld/frame'
6
6
  require 'json/ld/to_rdf'
7
7
  require 'json/ld/from_rdf'
8
8
 
9
+ begin
10
+ require 'jsonlint'
11
+ rescue LoadError
12
+ end
13
+
9
14
  module JSON::LD
10
15
  ##
11
16
  # A JSON-LD processor based on the JsonLdProcessor interface.
@@ -76,8 +81,10 @@ module JSON::LD
76
81
  # Use unique bnode identifiers, defaults to using the identifier which the node was originall initialized with (if any).
77
82
  # @option options [Boolean] :simple_compact_iris (false)
78
83
  # When compacting IRIs, do not use terms with expanded term definitions
84
+ # @option options [Boolean] :validate Validate input, if a string or readable object.
79
85
  # @yield [api]
80
86
  # @yieldparam [API]
87
+ # @raise [JsonLdError]
81
88
  def initialize(input, context, options = {}, &block)
82
89
  @options = {compactArrays: true, rename_bnodes: true}.merge(options)
83
90
  @options[:validate] = true if @options[:processingMode] == "json-ld-1.0"
@@ -99,6 +106,8 @@ module JSON::LD
99
106
  link.href if link
100
107
  end
101
108
 
109
+ validate_input(input) if options[:validate]
110
+
102
111
  JSON.parse(input.read)
103
112
  when String
104
113
  remote_doc = @options[:documentLoader].call(input, @options)
@@ -107,8 +116,11 @@ module JSON::LD
107
116
  context_ref = remote_doc.contextUrl
108
117
 
109
118
  case remote_doc.document
110
- when String then JSON.parse(remote_doc.document)
111
- else remote_doc.document
119
+ when String
120
+ validate_input(remote_doc.document) if options[:validate]
121
+ JSON.parse(remote_doc.document)
122
+ else
123
+ remote_doc.document
112
124
  end
113
125
  end
114
126
 
@@ -142,8 +154,9 @@ module JSON::LD
142
154
  # @yield jsonld
143
155
  # @yieldparam [Array<Hash>] jsonld
144
156
  # The expanded JSON-LD document
145
- # @return [Array<Hash>]
146
- # The expanded JSON-LD document
157
+ # @yieldreturn [Object] returned object
158
+ # @return [Object, Array<Hash>]
159
+ # If a block is given, the result of evaluating the block is returned, otherwise, the expanded JSON-LD document
147
160
  # @see http://json-ld.org/spec/latest/json-ld-api/#expansion-algorithm
148
161
  def self.expand(input, options = {})
149
162
  result = nil
@@ -157,8 +170,7 @@ module JSON::LD
157
170
 
158
171
  # Finally, if element is a JSON object, it is wrapped into an array.
159
172
  result = [result].compact unless result.is_a?(Array)
160
- yield result if block_given?
161
- result
173
+ block_given? ? yield(result) : result
162
174
  end
163
175
 
164
176
  ##
@@ -176,11 +188,13 @@ module JSON::LD
176
188
  # @param [Hash{Symbol => Object}] options
177
189
  # See options in {JSON::LD::API#initialize}
178
190
  # Other options passed to {JSON::LD::API.expand}
191
+ # @option options [Boolean] :expanded Input is already expanded
179
192
  # @yield jsonld
180
193
  # @yieldparam [Hash] jsonld
181
194
  # The compacted JSON-LD document
182
- # @return [Hash]
183
- # The compacted JSON-LD document
195
+ # @yieldreturn [Object] returned object
196
+ # @return [Object, Hash]
197
+ # If a block is given, the result of evaluating the block is returned, otherwise, the compacted JSON-LD document
184
198
  # @raise [JsonLdError]
185
199
  # @see http://json-ld.org/spec/latest/json-ld-api/#compaction-algorithm
186
200
  def self.compact(input, context, options = {})
@@ -188,7 +202,7 @@ module JSON::LD
188
202
 
189
203
  # 1) Perform the Expansion Algorithm on the JSON-LD input.
190
204
  # This removes any existing context to allow the given context to be cleanly applied.
191
- expanded = API.expand(input, options)
205
+ expanded = options[:expanded] ? input : API.expand(input, options)
192
206
 
193
207
  API.new(expanded, context, options) do
194
208
  debug(".compact") {"expanded input: #{expanded.to_json(JSON_STATE) rescue 'malformed json'}"}
@@ -202,8 +216,7 @@ module JSON::LD
202
216
  end
203
217
  result = ctx.merge(result) unless ctx.empty?
204
218
  end
205
- yield result if block_given?
206
- result
219
+ block_given? ? yield(result) : result
207
220
  end
208
221
 
209
222
  ##
@@ -218,30 +231,31 @@ module JSON::LD
218
231
  # @param [Hash{Symbol => Object}] options
219
232
  # See options in {JSON::LD::API#initialize}
220
233
  # Other options passed to {JSON::LD::API.expand}
234
+ # @option options [Boolean] :expanded Input is already expanded
221
235
  # @yield jsonld
222
236
  # @yieldparam [Hash] jsonld
223
- # The framed JSON-LD document
224
- # @return [Array<Hash>]
225
- # The framed JSON-LD document
226
- # @raise [InvalidFrame]
237
+ # The flattened JSON-LD document
238
+ # @yieldreturn [Object] returned object
239
+ # @return [Object, Hash]
240
+ # If a block is given, the result of evaluating the block is returned, otherwise, the flattened JSON-LD document
227
241
  # @see http://json-ld.org/spec/latest/json-ld-api/#framing-algorithm
228
242
  def self.flatten(input, context, options = {})
229
243
  flattened = []
230
244
 
231
245
  # Expand input to simplify processing
232
- expanded_input = API.expand(input, options)
246
+ expanded_input = options[:expanded] ? input : API.expand(input, options)
233
247
 
234
- # Initialize input using frame as context
248
+ # Initialize input using
235
249
  API.new(expanded_input, context, options) do
236
250
  debug(".flatten") {"expanded input: #{value.to_json(JSON_STATE) rescue 'malformed json'}"}
237
251
 
238
252
  # Initialize node map to a JSON object consisting of a single member whose key is @default and whose value is an empty JSON object.
239
- node_map = {'@default' => {}}
240
- self.generate_node_map(value, node_map)
253
+ graphs = {'@default' => {}}
254
+ create_node_map(value, graphs)
241
255
 
242
- default_graph = node_map['@default']
243
- node_map.keys.kw_sort.reject {|k| k == '@default'}.each do |graph_name|
244
- graph = node_map[graph_name]
256
+ default_graph = graphs['@default']
257
+ graphs.keys.kw_sort.reject {|k| k == '@default'}.each do |graph_name|
258
+ graph = graphs[graph_name]
245
259
  entry = default_graph[graph_name] ||= {'@id' => graph_name}
246
260
  nodes = entry['@graph'] ||= []
247
261
  graph.keys.kw_sort.each do |id|
@@ -261,8 +275,7 @@ module JSON::LD
261
275
  end
262
276
  end
263
277
 
264
- yield flattened if block_given?
265
- flattened
278
+ block_given? ? yield(flattened) : flattened
266
279
  end
267
280
 
268
281
  ##
@@ -279,34 +292,42 @@ module JSON::LD
279
292
  # @param [Hash{Symbol => Object}] options
280
293
  # See options in {JSON::LD::API#initialize}
281
294
  # Other options passed to {JSON::LD::API.expand}
282
- # @option options [Boolean] :embed (true)
295
+ # @option options ['@last', '@always', '@never', '@link'] :embed ('@link')
283
296
  # a flag specifying that objects should be directly embedded in the output,
284
297
  # instead of being referred to by their IRI.
285
298
  # @option options [Boolean] :explicit (false)
286
299
  # a flag specifying that for properties to be included in the output,
287
300
  # they must be explicitly declared in the framing context.
301
+ # @option options [Boolean] :requireAll (true)
288
302
  # @option options [Boolean] :omitDefault (false)
289
303
  # a flag specifying that properties that are missing from the JSON-LD
290
304
  # input should be omitted from the output.
305
+ # @option options [Boolean] :expanded Input is already expanded
291
306
  # @yield jsonld
292
307
  # @yieldparam [Hash] jsonld
293
308
  # The framed JSON-LD document
294
- # @return [Array<Hash>]
295
- # The framed JSON-LD document
309
+ # @yieldreturn [Object] returned object
310
+ # @return [Object, Hash]
311
+ # If a block is given, the result of evaluating the block is returned, otherwise, the framed JSON-LD document
296
312
  # @raise [InvalidFrame]
297
313
  # @see http://json-ld.org/spec/latest/json-ld-api/#framing-algorithm
298
314
  def self.frame(input, frame, options = {})
299
315
  result = nil
316
+ options = {
317
+ base: input.is_a?(String) ? input : '',
318
+ compactArrays: true,
319
+ embed: '@last',
320
+ explicit: false,
321
+ requireAll: true,
322
+ omitDefault: false,
323
+ documentLoader: method(:documentLoader)
324
+ }.merge(options)
325
+
300
326
  framing_state = {
301
- embed: true,
302
- explicit: false,
303
- omitDefault: false,
304
- embeds: nil,
327
+ graphs: {'@default' => {}, '@merged' => {}},
328
+ subjectStack: [],
329
+ link: {},
305
330
  }
306
- framing_state[:embed] = options[:embed] if options.has_key?(:embed)
307
- framing_state[:explicit] = options[:explicit] if options.has_key?(:explicit)
308
- framing_state[:omitDefault] = options[:omitDefault] if options.has_key?(:omitDefault)
309
- options[:documentLoader] ||= method(:documentLoader)
310
331
 
311
332
  # de-reference frame to create the framing object
312
333
  frame = case frame
@@ -321,7 +342,7 @@ module JSON::LD
321
342
  end
322
343
 
323
344
  # Expand input to simplify processing
324
- expanded_input = API.expand(input, options)
345
+ expanded_input = options[:expanded] ? input : API.expand(input, options)
325
346
 
326
347
  # Expand frame to simplify processing
327
348
  expanded_frame = API.expand(frame, options)
@@ -329,22 +350,17 @@ module JSON::LD
329
350
  # Initialize input using frame as context
330
351
  API.new(expanded_input, nil, options) do
331
352
  #debug(".frame") {"context from frame: #{context.inspect}"}
332
- debug(".frame") {"raw frame: #{frame.to_json(JSON_STATE) rescue 'malformed json'}"}
333
353
  debug(".frame") {"expanded frame: #{expanded_frame.to_json(JSON_STATE) rescue 'malformed json'}"}
334
- debug(".frame") {"expanded input: #{value.to_json(JSON_STATE) rescue 'malformed json'}"}
335
354
 
336
355
  # Get framing nodes from expanded input, replacing Blank Node identifiers as necessary
337
- all_nodes = {}
338
356
  old_dbg, @options[:debug] = @options[:debug], nil
339
- depth do
340
- generate_node_map(value, all_nodes)
341
- end
357
+ create_node_map(value, framing_state[:graphs], '@merged')
342
358
  @options[:debug] = old_dbg
343
- @node_map = all_nodes['@default']
344
- debug(".frame") {"node_map: #{@node_map.to_json(JSON_STATE) rescue 'malformed json'}"}
359
+ framing_state[:subjects] = framing_state[:graphs]['@merged']
360
+ debug(".frame") {"subjects: #{framing_state[:subjects].to_json(JSON_STATE) rescue 'malformed json'}"}
345
361
 
346
362
  result = []
347
- frame(framing_state, @node_map, (expanded_frame.first || {}), parent: result)
363
+ frame(framing_state, framing_state[:subjects].keys.sort, (expanded_frame.first || {}), options.merge(parent: result))
348
364
  debug(".frame") {"after frame: #{result.to_json(JSON_STATE) rescue 'malformed json'}"}
349
365
 
350
366
  # Initalize context from frame
@@ -360,8 +376,7 @@ module JSON::LD
360
376
  result = cleanup_preserve(result)
361
377
  end
362
378
 
363
- yield result if block_given?
364
- result
379
+ block_given? ? yield(result) : result
365
380
  end
366
381
 
367
382
  ##
@@ -374,9 +389,11 @@ module JSON::LD
374
389
  # Options passed to {JSON::LD::API.expand}
375
390
  # @option options [Boolean] :produceGeneralizedRdf (false)
376
391
  # If true, output will include statements having blank node predicates, otherwise they are dropped.
392
+ # @option options [Boolean] :expanded Input is already expanded
377
393
  # @raise [JsonLdError]
378
394
  # @yield statement
379
395
  # @yieldparam [RDF::Statement] statement
396
+ # @return [RDF::Enumerable] set of statements, unless a block is given.
380
397
  def self.toRdf(input, options = {}, &block)
381
398
  unless block_given?
382
399
  results = []
@@ -388,7 +405,7 @@ module JSON::LD
388
405
  end
389
406
 
390
407
  # Expand input to simplify processing
391
- expanded_input = API.expand(input, options.merge(ordered: false))
408
+ expanded_input = options[:expanded] ? input : API.expand(input, options.merge(ordered: false))
392
409
 
393
410
  API.new(expanded_input, nil, options) do
394
411
  # 1) Perform the Expansion Algorithm on the JSON-LD input.
@@ -396,12 +413,12 @@ module JSON::LD
396
413
  debug(".toRdf") {"expanded input: #{expanded_input.to_json(JSON_STATE) rescue 'malformed json'}"}
397
414
 
398
415
  # Generate _nodeMap_
399
- node_map = {'@default' => {}}
400
- generate_node_map(expanded_input, node_map)
401
- debug(".toRdf") {"node map: #{node_map.to_json(JSON_STATE) rescue 'malformed json'}"}
416
+ graphs = {'@default' => {}}
417
+ create_node_map(expanded_input, graphs)
418
+ debug(".toRdf") {"node map: #{graphs.to_json(JSON_STATE) rescue 'malformed json'}"}
402
419
 
403
420
  # Start generating statements
404
- node_map.each do |graph_name, graph|
421
+ graphs.each do |graph_name, graph|
405
422
  context = as_resource(graph_name) unless graph_name == '@default'
406
423
  debug(".toRdf") {"context: #{context ? context.to_ntriples : 'null'}"}
407
424
  # Drop results for graphs which are named with relative IRIs
@@ -436,7 +453,6 @@ module JSON::LD
436
453
  end
437
454
  end
438
455
  end
439
- results
440
456
  end
441
457
 
442
458
  ##
@@ -450,8 +466,9 @@ module JSON::LD
450
466
  # @yield jsonld
451
467
  # @yieldparam [Hash] jsonld
452
468
  # The JSON-LD document in expanded form
453
- # @return [Array<Hash>]
454
- # The JSON-LD document in expanded form
469
+ # @yieldreturn [Object] returned object
470
+ # @return [Object, Hash]
471
+ # If a block is given, the result of evaluating the block is returned, otherwise, the expanded JSON-LD document
455
472
  def self.fromRdf(input, options = {}, &block)
456
473
  options = {useNativeTypes: false}.merge(options)
457
474
  result = nil
@@ -460,8 +477,7 @@ module JSON::LD
460
477
  result = api.from_statements(input)
461
478
  end
462
479
 
463
- yield result if block_given?
464
- result
480
+ block_given? ? yield(result) : result
465
481
  end
466
482
 
467
483
  ##
@@ -470,9 +486,11 @@ module JSON::LD
470
486
  # @param [Hash<Symbol => Object>] options
471
487
  # @option options [Boolean] :validate
472
488
  # Allow only appropriate content types
473
- # @return [RemoteDocument] retrieved remote document and context information unless block given
474
489
  # @yield remote_document
475
490
  # @yieldparam [RemoteDocument] remote_document
491
+ # @yieldreturn [Object] returned object
492
+ # @return [Object, RemoteDocument]
493
+ # If a block is given, the result of evaluating the block is returned, otherwise, the retrieved remote document and context information unless block given
476
494
  # @raise [JsonLdError]
477
495
  def self.documentLoader(url, options = {})
478
496
  options = OPEN_OPTS.merge(options)
@@ -500,11 +518,7 @@ module JSON::LD
500
518
 
501
519
  doc_uri = remote_doc.base_uri rescue url
502
520
  doc = RemoteDocument.new(doc_uri, remote_doc.read, contextUrl)
503
- if block_given?
504
- yield(doc)
505
- else
506
- doc
507
- end
521
+ block_given? ? yield(doc) : doc
508
522
  end
509
523
  rescue IOError => e
510
524
  raise JSON::LD::JsonLdError::LoadingDocumentFailed, e.message
@@ -516,6 +530,21 @@ module JSON::LD
516
530
  alias :fromRDF :fromRdf
517
531
  end
518
532
 
533
+ private
534
+ def validate_input(input)
535
+ return unless defined?(JsonLint)
536
+ jsonlint = JsonLint::Linter.new
537
+ unless jsonlint.respond_to?(:check_stream)
538
+ warn "Skipping jsonlint, use latest version from GiHub until 0.1.1 released"
539
+ return
540
+ end
541
+ input = StringIO.new(input) unless input.respond_to?(:read)
542
+ unless jsonlint.check_stream(input)
543
+ raise JsonLdError::LoadingDocumentFailed, jsonlint.errors[''].join("\n")
544
+ end
545
+ input.rewind
546
+ end
547
+
519
548
  ##
520
549
  # A {RemoteDocument} is returned from a {documentLoader}.
521
550
  class RemoteDocument
@@ -155,7 +155,7 @@ module JSON::LD
155
155
  # @return [Context]
156
156
  def initialize(options = {})
157
157
  if options[:base]
158
- @base = @doc_base = RDF::URI(options[:base])
158
+ @base = @doc_base = RDF::URI(options[:base]).dup
159
159
  @doc_base.canonicalize!
160
160
  @doc_base.fragment = nil
161
161
  @doc_base.query = nil
@@ -198,7 +198,7 @@ module JSON::LD
198
198
  def base=(value)
199
199
  if value
200
200
  raise JsonLdError::InvalidBaseIRI, "@base must be a string: #{value.inspect}" unless value.is_a?(String) || value.is_a?(RDF::URI)
201
- @base = RDF::URI(value)
201
+ @base = RDF::URI(value).dup
202
202
  @base.canonicalize!
203
203
  @base.fragment = nil
204
204
  @base.query = nil
@@ -182,7 +182,7 @@ module JSON::LD
182
182
 
183
183
  # Continue with the next key from element
184
184
  next
185
- when '@explicit', '@default', '@embed', '@embedChildren', '@omitDefault'
185
+ when '@explicit', '@default', '@embed', '@explicit', '@omitDefault', '@preserve', '@requireAll'
186
186
  # Framing keywords
187
187
  depth { [expand(value, expanded_property, context, options)].flatten }
188
188
  else
@@ -1,37 +1,4 @@
1
1
  module RDF
2
- class Graph
3
- # Resource properties
4
- #
5
- # Properties arranged as a hash with the predicate Term as index to an array of resources or literals
6
- #
7
- # Example:
8
- # graph.load(':foo a :bar; rdfs:label "An example" .', "http://example.com/")
9
- # graph.resources(URI.new("http://example.com/subject")) =>
10
- # {
11
- # "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" => \[<http://example.com/#bar>\],
12
- # "http://example.com/#label" => \["An example"\]
13
- # }
14
- def properties(subject, recalc = false)
15
- @properties ||= {}
16
- @properties.delete(subject.to_s) if recalc
17
- @properties[subject.to_s] ||= begin
18
- hash = Hash.new
19
- self.query(subject: subject) do |statement|
20
- pred = statement.predicate.to_s
21
-
22
- hash[pred] ||= []
23
- hash[pred] << statement.object
24
- end
25
- hash
26
- end
27
- end
28
-
29
- # Get type(s) of subject, returns a list of symbols
30
- def type_of(subject)
31
- query(subject: subject, predicate: RDF.type).map {|st| st.object}
32
- end
33
- end
34
-
35
2
  class Node
36
3
  # Odd case of appending to a BNode identifier
37
4
  def +(value)