json-ld 1.1.8 → 1.1.9

Sign up to get free protection for your applications and to get access to all the features.
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)