json-ld 2.2.1 → 3.0.0

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
- SHA1:
3
- metadata.gz: 8da5138b7c0078bf7da59b61dfdc302c363c49ad
4
- data.tar.gz: 512ae330ada362f55597cc3cc5d2d2fb14875d4b
2
+ SHA256:
3
+ metadata.gz: 33d72fb295b05e075532454ade144d79cf15458946492639f9a941a62668c510
4
+ data.tar.gz: a382b3bdf08bc1b377d5d01f8d2bae93631e7f9077161fd6bbddfd7477a4c775
5
5
  SHA512:
6
- metadata.gz: 7ef0402a7b79e8e9bd24195a5026659cf6e50dd714aeb154bbce0dab447e491be86eaa4a250ef2457e3eb1af0a811858226cd09d32c0107f2c75400873b5d805
7
- data.tar.gz: 664a8bcff91f18cb804c8c69a7fc44e40219fdca8c619695e6a69ef6f6d4362e90e9e3cc6f4c33bab412f75ab87e6aee2a732ffc8eb632686df53c7a4afbb1f4
6
+ metadata.gz: fea935d4ce21a779b4d6eb2bd38eaf8f0859b4e312b8baa509e3325663597cffcef934e3210dda62e339b08d86dc689458fc331b5edf86e500b28ffbe4679548
7
+ data.tar.gz: 1d589f193efd2725ac4ac4d200de04fea6d13296fa7ad3989cf40cfed30424dd91dfb27ced0eda4ce88d0f5676e90b36e5b4cff8185afac9644fd3cc7edd7c0a
data/README.md CHANGED
@@ -28,13 +28,13 @@ This gem implements an optimized streaming writer used for generating JSON-LD fr
28
28
  * RDF Lists are written as separate nodes using `rdf:first` and `rdf:rest` properties.
29
29
 
30
30
  ## Examples
31
-
32
- require 'rubygems'
33
- require 'json/ld'
34
-
31
+ ```ruby
32
+ require 'rubygems'
33
+ require 'json/ld'
34
+ ```
35
35
  ### Expand a Document
36
-
37
- input = JSON.parse %({
36
+ ```ruby
37
+ input = JSON.parse %({
38
38
  "@context": {
39
39
  "name": "http://xmlns.com/foaf/0.1/name",
40
40
  "homepage": "http://xmlns.com/foaf/0.1/homepage",
@@ -51,9 +51,9 @@ This gem implements an optimized streaming writer used for generating JSON-LD fr
51
51
  "http://xmlns.com/foaf/0.1/homepage": [{"@value"=>"http://manu.sporny.org/"}],
52
52
  "http://xmlns.com/foaf/0.1/avatar": [{"@value": "http://twitter.com/account/profile_image/manusporny"}]
53
53
  }]
54
-
54
+ ```
55
55
  ### Compact a Document
56
-
56
+ ```ruby
57
57
  input = JSON.parse %([{
58
58
  "http://xmlns.com/foaf/0.1/name": ["Manu Sporny"],
59
59
  "http://xmlns.com/foaf/0.1/homepage": [{"@id": "http://manu.sporny.org/"}],
@@ -79,9 +79,9 @@ This gem implements an optimized streaming writer used for generating JSON-LD fr
79
79
  "homepage": "http://manu.sporny.org/",
80
80
  "name": "Manu Sporny"
81
81
  }
82
-
82
+ ```
83
83
  ### Frame a Document
84
-
84
+ ```ruby
85
85
  input = JSON.parse %({
86
86
  "@context": {
87
87
  "Book": "http://example.org/vocab#Book",
@@ -162,9 +162,9 @@ This gem implements an optimized streaming writer used for generating JSON-LD fr
162
162
  }
163
163
  ]
164
164
  }
165
-
165
+ ```
166
166
  ### Turn JSON-LD into RDF (Turtle)
167
-
167
+ ```ruby
168
168
  input = JSON.parse %({
169
169
  "@context": {
170
170
  "": "http://manu.sporny.org/",
@@ -185,9 +185,9 @@ This gem implements an optimized streaming writer used for generating JSON-LD fr
185
185
  <http://example.org/people#joebob> a foaf:Person;
186
186
  foaf:name "Joe Bob";
187
187
  foaf:nick ("joe" "bob" "jaybe") .
188
-
188
+ ```
189
189
  ### Turn RDF into JSON-LD
190
-
190
+ ```ruby
191
191
  require 'rdf/turtle'
192
192
  input = RDF::Graph.new << RDF::Turtle::Reader.new(%(
193
193
  @prefix foaf: <http://xmlns.com/foaf/0.1/> .
@@ -223,12 +223,12 @@ This gem implements an optimized streaming writer used for generating JSON-LD fr
223
223
  "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}]
224
224
  }
225
225
  ]
226
-
226
+ ```
227
227
  ## Use a custom Document Loader
228
228
  In some cases, the built-in document loader {JSON::LD::API.documentLoader} is inadequate; for example, when using `http://schema.org` as a remote context, it will be re-loaded every time.
229
229
 
230
230
  All entries into the {JSON::LD::API} accept a `:documentLoader` option, which can be used to provide an alternative method to use when loading remote documents. For example:
231
-
231
+ ```ruby
232
232
  def load_document_local(url, options={}, &block)
233
233
  if RDF::URI(url, canonicalize: true) == RDF::URI('http://schema.org/')
234
234
  remote_document = JSON::LD::API::RemoteDocument.new(url, File.read("etc/schema.org.jsonld"))
@@ -237,28 +237,28 @@ All entries into the {JSON::LD::API} accept a `:documentLoader` option, which ca
237
237
  JSON::LD::API.documentLoader(url, options, &block)
238
238
  end
239
239
  end
240
-
240
+ ```
241
241
  Then, when performing something like expansion:
242
-
242
+ ```ruby
243
243
  JSON::LD::API.expand(input, documentLoader: load_document_local)
244
-
244
+ ```
245
245
 
246
246
  ## Preloading contexts
247
247
  In many cases, for small documents, processing time can be dominated by loading and parsing remote contexts. In particular, a small schema.org example may need to download a large context and turn it into an internal representation, before the actual document can be expanded for processing. Using {JSON::LD::Context.add_preloaded}, an implementation can perform this loading up-front, and make it available to the processor.
248
-
248
+ ```ruby
249
249
  ctx = JSON::LD::Context.new().parse('http://schema.org/')
250
250
  JSON::LD::Context.add_preloaded('http://schema.org/', ctx)
251
-
251
+ ```
252
252
  On lookup, URIs with an `https` prefix are normalized to `http`.
253
253
 
254
254
  A context may be serialized to Ruby to speed this process using `Context#to_rb`. When loaded, this generated file will add entries to the {JSON::LD::Context::PRELOADED}.
255
255
 
256
256
  ## RDF Reader and Writer
257
257
  {JSON::LD} also acts as a normal RDF reader and writer, using the standard RDF.rb reader/writer interfaces:
258
-
258
+ ```ruby
259
259
  graph = RDF::Graph.load("etc/doap.jsonld", format: :jsonld)
260
260
  graph.dump(:jsonld, standard_prefixes: true)
261
-
261
+ ```
262
262
  `RDF::GRAPH#dump` can also take a `:context` option to use a separately defined context
263
263
 
264
264
  As JSON-LD may come from many different sources, included as an embedded script tag within an HTML document, the RDF Reader will strip input before the leading `{` or `[` and after the trailing `}` or `]`.
@@ -268,7 +268,7 @@ This implementation is being used as a test-bed for features planned for an upco
268
268
 
269
269
  ### Scoped Contexts
270
270
  A term definition can include `@context`, which is applied to values of that object. This is also used when compacting. Taken together, this allows framing to effectively include context definitions more deeply within the framed structure.
271
-
271
+ ```ruby
272
272
  {
273
273
  "@context": {
274
274
  "ex": "http://example.com/",
@@ -283,10 +283,10 @@ A term definition can include `@context`, which is applied to values of that obj
283
283
  },
284
284
  "foo": "Bar"
285
285
  }
286
-
286
+ ```
287
287
  ### @id and @type maps
288
288
  The value of `@container` in a term definition can include `@id` or `@type`, in addition to `@set`, `@list`, `@language`, and `@index`. This allows value indexing based on either the `@id` or `@type` of associated objects.
289
-
289
+ ```ruby
290
290
  {
291
291
  "@context": {
292
292
  "@vocab": "http://example/",
@@ -297,10 +297,10 @@ The value of `@container` in a term definition can include `@id` or `@type`, in
297
297
  "_:bar": {"label": "Object with @id _:bar"}
298
298
  }
299
299
  }
300
-
300
+ ```
301
301
  ### @graph containers and maps
302
302
  A term can have `@container` set to include `@graph` optionally including `@id` or `@index` and `@set`. In the first form, with `@container` set to `@graph`, the value of a property is treated as a _simple graph object_, meaning that values treated as if they were contained in an object with `@graph`, creating _named graph_ with an anonymous name.
303
-
303
+ ```ruby
304
304
  {
305
305
  "@context": {
306
306
  "@vocab": "http://example.org/",
@@ -310,9 +310,9 @@ A term can have `@container` set to include `@graph` optionally including `@id`
310
310
  "value": "x"
311
311
  }
312
312
  }
313
-
313
+ ```
314
314
  which expands to the following:
315
-
315
+ ```ruby
316
316
  [{
317
317
  "http://example.org/input": [{
318
318
  "@graph": [{
@@ -320,18 +320,18 @@ which expands to the following:
320
320
  }]
321
321
  }]
322
322
  }]
323
-
323
+ ```
324
324
  Compaction reverses this process, optionally ensuring that a single value is contained within an array of `@container` also includes `@set`:
325
-
325
+ ```ruby
326
326
  {
327
327
  "@context": {
328
328
  "@vocab": "http://example.org/",
329
329
  "input": {"@container": ["@graph", "@set"]}
330
330
  }
331
331
  }
332
-
332
+ ```
333
333
  A graph map uses the map form already existing for `@index`, `@language`, `@type`, and `@id` where the index is either an index value or an id.
334
-
334
+ ```ruby
335
335
  {
336
336
  "@context": {
337
337
  "@vocab": "http://example.org/",
@@ -341,9 +341,9 @@ A graph map uses the map form already existing for `@index`, `@language`, `@type
341
341
  "g1": {"value": "x"}
342
342
  }
343
343
  }
344
-
344
+ ```
345
345
  treats "g1" as an index, and expands to the following:
346
-
346
+ ```ruby
347
347
  [{
348
348
  "http://example.org/input": [{
349
349
  "@index": "g1",
@@ -352,11 +352,11 @@ treats "g1" as an index, and expands to the following:
352
352
  }]
353
353
  }]
354
354
  }])
355
-
355
+ ```
356
356
  This can also include `@set` to ensure that, when compacting, a single value of an index will be in array form.
357
357
 
358
358
  The _id_ version is similar:
359
-
359
+ ```ruby
360
360
  {
361
361
  "@context": {
362
362
  "@vocab": "http://example.org/",
@@ -366,9 +366,9 @@ The _id_ version is similar:
366
366
  "http://example.com/g1": {"value": "x"}
367
367
  }
368
368
  }
369
-
369
+ ```
370
370
  which expands to:
371
-
371
+ ```ruby
372
372
  [{
373
373
  "http://example.org/input": [{
374
374
  "@id": "http://example.com/g1",
@@ -377,10 +377,10 @@ which expands to:
377
377
  }]
378
378
  }]
379
379
  }])
380
-
380
+ ```
381
381
  ### Transparent Nesting
382
382
  Many JSON APIs separate properties from their entities using an intermediate object. For example, a set of possible labels may be grouped under a common property:
383
-
383
+ ```json
384
384
  {
385
385
  "@context": {
386
386
  "skos": "http://www.w3.org/2004/02/skos/core#",
@@ -396,9 +396,9 @@ Many JSON APIs separate properties from their entities using an intermediate obj
396
396
  "other_label": "This is the other label"
397
397
  }
398
398
  }
399
-
399
+ ```
400
400
  In this case, the `labels` property is semantically meaningless. Defining it as equivalent to `@nest` causes it to be ignored when expanding, making it equivalent to the following:
401
-
401
+ ```json
402
402
  {
403
403
  "@context": {
404
404
  "skos": "http://www.w3.org/2004/02/skos/core#",
@@ -412,9 +412,9 @@ Many JSON APIs separate properties from their entities using an intermediate obj
412
412
  "main_label": "This is the main label for my resource",
413
413
  "other_label": "This is the other label"
414
414
  }
415
-
415
+ ```
416
416
  Similarly, properties may be marked with "@nest": "nest-term", to cause them to be nested. Note that the `@nest` keyword can also be aliased in the context.
417
-
417
+ ```json
418
418
  {
419
419
  "@context": {
420
420
  "skos": "http://www.w3.org/2004/02/skos/core#",
@@ -430,7 +430,7 @@ Many JSON APIs separate properties from their entities using an intermediate obj
430
430
  "other_label": "This is the other label"
431
431
  }
432
432
  }
433
-
433
+ ```
434
434
  In this way, nesting survives round-tripping through expansion, and framed output can include nested properties.
435
435
 
436
436
  ### Framing Updates
@@ -469,20 +469,20 @@ Note, the API method signatures differed in versions before 1.0, in that they al
469
469
 
470
470
  ## Dependencies
471
471
  * [Ruby](http://ruby-lang.org/) (>= 2.2.2)
472
- * [RDF.rb](http://rubygems.org/gems/rdf) (>= 2.2)
473
- * [JSON](https://rubygems.org/gems/json) (>= 1.5)
472
+ * [RDF.rb](http://rubygems.org/gems/rdf) (~> 3.0)
473
+ * [JSON](https://rubygems.org/gems/json) (>= 2.1)
474
474
 
475
475
  ## Installation
476
476
  The recommended installation method is via [RubyGems](http://rubygems.org/).
477
477
  To install the latest official release of the `JSON-LD` gem, do:
478
-
479
- % [sudo] gem install json-ld
480
-
478
+ ```bash
479
+ % [sudo] gem install json-ld
480
+ ```
481
481
  ## Download
482
482
  To get a local working copy of the development repository, do:
483
-
484
- % git clone git://github.com/ruby-rdf/json-ld.git
485
-
483
+ ```bash
484
+ % git clone git://github.com/ruby-rdf/json-ld.git
485
+ ```
486
486
  ## Mailing List
487
487
  * <http://lists.w3.org/Archives/Public/public-rdf-ruby/>
488
488
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.2.1
1
+ 3.0.0
@@ -55,6 +55,7 @@ module JSON
55
55
  @language
56
56
  @list
57
57
  @nest
58
+ @none
58
59
  @omitDefault
59
60
  @requireAll
60
61
  @reverse
@@ -90,6 +91,8 @@ module JSON
90
91
  array_nl: "\n"
91
92
  )
92
93
 
94
+ MAX_CONTEXTS_LOADED = 50
95
+
93
96
  class JsonLdError < StandardError
94
97
  def to_s
95
98
  "#{self.class.instance_variable_get :@code}: #{super}"
@@ -99,7 +102,6 @@ module JSON
99
102
  end
100
103
 
101
104
  class CollidingKeywords < JsonLdError; @code = "colliding keywords"; end
102
- class CompactionToListOfLists < JsonLdError; @code = "compaction to list of lists"; end
103
105
  class ConflictingIndexes < JsonLdError; @code = "conflicting indexes"; end
104
106
  class CyclicIRIMapping < JsonLdError; @code = "cyclic IRI mapping"; end
105
107
  class InvalidBaseIRI < JsonLdError; @code = "invalid base IRI"; end
@@ -132,9 +134,9 @@ module JSON
132
134
  class InvalidValueObjectValue < JsonLdError; @code = "invalid value object value"; end
133
135
  class InvalidVocabMapping < JsonLdError; @code = "invalid vocab mapping"; end
134
136
  class KeywordRedefinition < JsonLdError; @code = "keyword redefinition"; end
135
- class ListOfLists < JsonLdError; @code = "list of lists"; end
136
137
  class LoadingDocumentFailed < JsonLdError; @code = "loading document failed"; end
137
138
  class LoadingRemoteContextFailed < JsonLdError; @code = "loading remote context failed"; end
139
+ class ContextOverflow < JsonLdError; @code = "maximum number of @context URLs exceeded"; end
138
140
  class MultipleContextLinkHeaders < JsonLdError; @code = "multiple context link headers"; end
139
141
  class ProcessingModeConflict < JsonLdError; @code = "processing mode conflict"; end
140
142
  class RecursiveContextInclusion < JsonLdError; @code = "recursive context inclusion"; end
@@ -72,10 +72,7 @@ module JSON::LD
72
72
  # @option options [Boolean, String, RDF::URI] :flatten
73
73
  # If set to a value that is not `false`, the JSON-LD processor must modify the output of the Compaction Algorithm or the Expansion Algorithm by coalescing all properties associated with each subject via the Flattening Algorithm. The value of `flatten must` be either an _IRI_ value representing the name of the graph to flatten, or `true`. If the value is `true`, then the first graph encountered in the input document is selected and flattened.
74
74
  # @option options [String] :processingMode
75
- # Processing mode, json-ld-1.0 or json-ld-1.1. Also can have other values:
76
- #
77
- # * json-ld-1.1-expand-frame – special frame expansion mode.
78
- #
75
+ # Processing mode, json-ld-1.0 or json-ld-1.1.
79
76
  # If `processingMode` is not specified, a mode of `json-ld-1.0` or `json-ld-1.1` is set, the context used for `expansion` or `compaction`.
80
77
  # @option options [Boolean] :rename_bnodes (true)
81
78
  # Rename bnodes as part of expansion, or keep them the same.
@@ -86,16 +83,15 @@ module JSON::LD
86
83
  # @yield [api]
87
84
  # @yieldparam [API]
88
85
  # @raise [JsonLdError]
89
- def initialize(input, context, options = {}, &block)
86
+ def initialize(input, context, rename_bnodes: true, unique_bnodes: false, **options, &block)
90
87
  @options = {
91
88
  compactArrays: true,
92
- rename_bnodes: true,
93
89
  documentLoader: self.class.method(:documentLoader)
94
90
  }.merge(options)
95
- @namer = options[:unique_bnodes] ? BlankNodeUniqer.new : (@options[:rename_bnodes] ? BlankNodeNamer.new("b") : BlankNodeMapper.new)
91
+ @namer = unique_bnodes ? BlankNodeUniqer.new : (rename_bnodes ? BlankNodeNamer.new("b") : BlankNodeMapper.new)
96
92
 
97
93
  # For context via Link header
98
- remote_base, context_ref = nil, nil
94
+ _, context_ref = nil, nil
99
95
 
100
96
  @value = case input
101
97
  when Array, Hash then input.dup
@@ -115,7 +111,6 @@ module JSON::LD
115
111
  when String
116
112
  remote_doc = @options[:documentLoader].call(input, @options)
117
113
 
118
- remote_base = remote_doc.documentUrl
119
114
  context_ref = remote_doc.contextUrl
120
115
  @options = {base: remote_doc.documentUrl}.merge(@options) unless @options[:no_default_base]
121
116
 
@@ -166,10 +161,12 @@ module JSON::LD
166
161
  # @return [Object, Array<Hash>]
167
162
  # If a block is given, the result of evaluating the block is returned, otherwise, the expanded JSON-LD document
168
163
  # @see http://json-ld.org/spec/latest/json-ld-api/#expansion-algorithm
169
- def self.expand(input, options = {}, &block)
164
+ def self.expand(input, ordered: true, framing: false, **options, &block)
170
165
  result, doc_base = nil
171
166
  API.new(input, options[:expandContext], options) do
172
- result = self.expand(self.value, nil, self.context, ordered: options.fetch(:ordered, true))
167
+ result = self.expand(self.value, nil, self.context,
168
+ ordered: ordered,
169
+ framing: framing)
173
170
  doc_base = @options[:base]
174
171
  end
175
172
 
@@ -213,18 +210,18 @@ module JSON::LD
213
210
  # If a block is given, the result of evaluating the block is returned, otherwise, the compacted JSON-LD document
214
211
  # @raise [JsonLdError]
215
212
  # @see http://json-ld.org/spec/latest/json-ld-api/#compaction-algorithm
216
- def self.compact(input, context, options = {})
213
+ def self.compact(input, context, expanded: false, **options)
217
214
  result = nil
218
215
  options = {compactToRelative: true}.merge(options)
219
216
 
220
217
  # 1) Perform the Expansion Algorithm on the JSON-LD input.
221
218
  # This removes any existing context to allow the given context to be cleanly applied.
222
- expanded_input = options[:expanded] ? input : API.expand(input, options) do |result, base_iri|
219
+ expanded_input = expanded ? input : API.expand(input, options) do |res, base_iri|
223
220
  options[:base] ||= base_iri if options[:compactToRelative]
224
- result
221
+ res
225
222
  end
226
223
 
227
- API.new(expanded_input, context, options.merge(no_default_base: true)) do
224
+ API.new(expanded_input, context, no_default_base: true, **options) do
228
225
  log_debug(".compact") {"expanded input: #{expanded_input.to_json(JSON_STATE) rescue 'malformed json'}"}
229
226
  result = compact(value)
230
227
 
@@ -258,18 +255,18 @@ module JSON::LD
258
255
  # @return [Object, Hash]
259
256
  # If a block is given, the result of evaluating the block is returned, otherwise, the flattened JSON-LD document
260
257
  # @see http://json-ld.org/spec/latest/json-ld-api/#framing-algorithm
261
- def self.flatten(input, context, options = {})
258
+ def self.flatten(input, context, expanded: false, **options)
262
259
  flattened = []
263
260
  options = {compactToRelative: true}.merge(options)
264
261
 
265
262
  # Expand input to simplify processing
266
- expanded_input = options[:expanded] ? input : API.expand(input, options) do |result, base_iri|
263
+ expanded_input = expanded ? input : API.expand(input, options) do |result, base_iri|
267
264
  options[:base] ||= base_iri if options[:compactToRelative]
268
265
  result
269
266
  end
270
267
 
271
268
  # Initialize input using
272
- API.new(expanded_input, context, options.merge(no_default_base: true)) do
269
+ API.new(expanded_input, context, no_default_base: true, **options) do
273
270
  log_debug(".flatten") {"expanded input: #{value.to_json(JSON_STATE) rescue 'malformed json'}"}
274
271
 
275
272
  # Initialize node map to a JSON object consisting of a single member whose key is @default and whose value is an empty JSON object.
@@ -277,24 +274,23 @@ module JSON::LD
277
274
  create_node_map(value, graph_maps)
278
275
 
279
276
  default_graph = graph_maps['@default']
280
- graph_maps.keys.kw_sort.each do |graph_name|
277
+ graph_maps.keys.sort.each do |graph_name|
281
278
  next if graph_name == '@default'
282
279
 
283
280
  graph = graph_maps[graph_name]
284
281
  entry = default_graph[graph_name] ||= {'@id' => graph_name}
285
282
  nodes = entry['@graph'] ||= []
286
- graph.keys.kw_sort.each do |id|
283
+ graph.keys.sort.each do |id|
287
284
  nodes << graph[id] unless node_reference?(graph[id])
288
285
  end
289
286
  end
290
- default_graph.keys.kw_sort.each do |id|
287
+ default_graph.keys.sort.each do |id|
291
288
  flattened << default_graph[id] unless node_reference?(default_graph[id])
292
289
  end
293
290
 
294
291
  if context && !flattened.empty?
295
292
  # Otherwise, return the result of compacting flattened according the Compaction algorithm passing context ensuring that the compaction result uses the @graph keyword (or its alias) at the top-level, even if the context is empty or if there is only one element to put in the @graph array. This ensures that the returned document has a deterministic structure.
296
- compacted = compact(flattened)
297
- compacted = [compacted] unless compacted.is_a?(Array)
293
+ compacted = as_array(compact(flattened))
298
294
  kwgraph = self.context.compact_iri('@graph', quiet: true)
299
295
  flattened = self.context.serialize.merge(kwgraph => compacted)
300
296
  end
@@ -322,7 +318,7 @@ module JSON::LD
322
318
  # @option options [Boolean] :omitDefault (false)
323
319
  # a flag specifying that properties that are missing from the JSON-LD input should be omitted from the output.
324
320
  # @option options [Boolean] :expanded Input is already expanded
325
- # @option options [Boolean] :pruneBlankNodeIdentifiers (true) removes blank node identifiers that are only used once.
321
+ # @option options [Boolean] :omitGraph does not use `@graph` at top level unless necessary to describe multiple objects, defaults to `true` if processingMode is 1.1, otherwise `false`.
326
322
  # @yield jsonld
327
323
  # @yieldparam [Hash] jsonld
328
324
  # The framed JSON-LD document
@@ -331,7 +327,7 @@ module JSON::LD
331
327
  # If a block is given, the result of evaluating the block is returned, otherwise, the framed JSON-LD document
332
328
  # @raise [InvalidFrame]
333
329
  # @see http://json-ld.org/spec/latest/json-ld-api/#framing-algorithm
334
- def self.frame(input, frame, options = {})
330
+ def self.frame(input, frame, expanded: false, **options)
335
331
  result = nil
336
332
  options = {
337
333
  base: (input if input.is_a?(String)),
@@ -341,7 +337,7 @@ module JSON::LD
341
337
  explicit: false,
342
338
  requireAll: true,
343
339
  omitDefault: false,
344
- pruneBlankNodeIdentifiers: true,
340
+ omitGraph: false,
345
341
  documentLoader: method(:documentLoader)
346
342
  }.merge(options)
347
343
 
@@ -365,20 +361,21 @@ module JSON::LD
365
361
  end
366
362
 
367
363
  # Expand input to simplify processing
368
- expanded_input = options[:expanded] ? input : API.expand(input, options) do |result, base_iri|
364
+ expanded_input = expanded ? input : API.expand(input, options) do |res, base_iri|
369
365
  options[:base] ||= base_iri if options[:compactToRelative]
370
- result
366
+ res
371
367
  end
372
368
 
373
369
  # Expand frame to simplify processing
374
- expanded_frame = API.expand(frame, options.merge(processingMode: "json-ld-1.1-expand-frame"))
370
+ expanded_frame = API.expand(frame, framing: true, **options)
375
371
 
376
372
  # Initialize input using frame as context
377
- API.new(expanded_input, nil, options.merge(no_default_base: true)) do
373
+ API.new(expanded_input, frame['@context'], no_default_base: true, **options) do
374
+ log_debug(".frame") {"expanded input: #{expanded_input.to_json(JSON_STATE) rescue 'malformed json'}"}
378
375
  log_debug(".frame") {"expanded frame: #{expanded_frame.to_json(JSON_STATE) rescue 'malformed json'}"}
379
376
 
380
377
  # Get framing nodes from expanded input, replacing Blank Node identifiers as necessary
381
- create_node_map(value, framing_state[:graphMap], graph: '@default')
378
+ create_node_map(value, framing_state[:graphMap], active_graph: '@default')
382
379
 
383
380
  frame_keys = frame.keys.map {|k| context.expand_iri(k, vocab: true, quiet: true)}
384
381
  if frame_keys.include?('@graph')
@@ -394,24 +391,29 @@ module JSON::LD
394
391
  framing_state[:subjects] = framing_state[:graphMap][framing_state[:graph]]
395
392
 
396
393
  result = []
397
- frame(framing_state, framing_state[:subjects].keys.sort, (expanded_frame.first || {}), options.merge(parent: result))
394
+ frame(framing_state, framing_state[:subjects].keys.sort, (expanded_frame.first || {}), parent: result, **options)
398
395
 
399
396
  # Count blank node identifiers used in the document, if pruning
400
- bnodes_to_clear = if options[:pruneBlankNodeIdentifiers]
401
- count_blank_node_identifiers(result).collect {|k, v| k if v == 1}.compact
397
+ unless @options[:processingMode] == 'json-ld-1.0'
398
+ bnodes_to_clear = count_blank_node_identifiers(result).collect {|k, v| k if v == 1}.compact
399
+ result = prune_bnodes(result, bnodes_to_clear)
402
400
  end
403
401
 
404
402
  # Initalize context from frame
405
403
  @context = @context.parse(frame['@context'])
406
404
  # Compact result
407
405
  compacted = compact(result)
408
- compacted = [compacted] unless compacted.is_a?(Array)
406
+ compacted = [compacted] unless options[:omitGraph] || compacted.is_a?(Array)
409
407
 
410
408
  # Add the given context to the output
411
- kwgraph = context.compact_iri('@graph', quiet: true)
412
- result = context.serialize.merge({kwgraph => compacted})
409
+ result = if !compacted.is_a?(Array)
410
+ context.serialize.merge(compacted)
411
+ else
412
+ kwgraph = context.compact_iri('@graph', quiet: true)
413
+ context.serialize.merge({kwgraph => compacted})
414
+ end
413
415
  log_debug(".frame") {"after compact: #{result.to_json(JSON_STATE) rescue 'malformed json'}"}
414
- result = cleanup_preserve(result, bnodes_to_clear || [])
416
+ result = cleanup_preserve(result)
415
417
  end
416
418
 
417
419
  block_given? ? yield(result) : result
@@ -430,7 +432,7 @@ module JSON::LD
430
432
  # @yield statement
431
433
  # @yieldparam [RDF::Statement] statement
432
434
  # @return [RDF::Enumerable] set of statements, unless a block is given.
433
- def self.toRdf(input, options = {}, &block)
435
+ def self.toRdf(input, expanded: false, **options, &block)
434
436
  unless block_given?
435
437
  results = []
436
438
  results.extend(RDF::Enumerable)
@@ -441,7 +443,7 @@ module JSON::LD
441
443
  end
442
444
 
443
445
  # Expand input to simplify processing
444
- expanded_input = options[:expanded] ? input : API.expand(input, options.merge(ordered: false))
446
+ expanded_input = expanded ? input : API.expand(input, ordered: false, **options)
445
447
 
446
448
  API.new(expanded_input, nil, options) do
447
449
  # 1) Perform the Expansion Algorithm on the JSON-LD input.
@@ -453,19 +455,9 @@ module JSON::LD
453
455
  item_to_rdf(node) do |statement|
454
456
  next if statement.predicate.node? && !options[:produceGeneralizedRdf]
455
457
 
456
- # Drop results with relative IRIs
457
- relative = statement.to_a.any? do |r|
458
- case r
459
- when RDF::URI
460
- r.relative?
461
- when RDF::Literal
462
- r.has_datatype? && r.datatype.relative?
463
- else
464
- false
465
- end
466
- end
467
- if relative
468
- log_debug(".toRdf") {"drop statement with relative IRIs: #{statement.to_ntriples}"}
458
+ # Drop invalid statements (other than IRIs)
459
+ unless statement.valid_extended?
460
+ log_debug(".toRdf") {"drop invalid statement: #{statement.to_nquads}"}
469
461
  next
470
462
  end
471
463
 
@@ -480,7 +472,7 @@ module JSON::LD
480
472
  #
481
473
  # The resulting `Array` is either returned or yielded, if a block is given.
482
474
  #
483
- # @param [Array<RDF::Statement>] input
475
+ # @param [RDF::Enumerable] input
484
476
  # @param [Hash{Symbol => Object}] options
485
477
  # @option options (see #initialize)
486
478
  # @option options [Boolean] :useRdfType (false)
@@ -492,9 +484,7 @@ module JSON::LD
492
484
  # @yieldreturn [Object] returned object
493
485
  # @return [Object, Hash]
494
486
  # If a block is given, the result of evaluating the block is returned, otherwise, the expanded JSON-LD document
495
- def self.fromRdf(input, options = {}, &block)
496
- useRdfType = options.fetch(:useRdfType, false)
497
- useNativeTypes = options.fetch(:useNativeTypes, false)
487
+ def self.fromRdf(input, useRdfType: false, useNativeTypes: false, **options, &block)
498
488
  result = nil
499
489
 
500
490
  API.new(nil, nil, options) do |api|
@@ -516,12 +506,12 @@ module JSON::LD
516
506
  # @return [Object, RemoteDocument]
517
507
  # If a block is given, the result of evaluating the block is returned, otherwise, the retrieved remote document and context information unless block given
518
508
  # @raise [JsonLdError]
519
- def self.documentLoader(url, options = {})
509
+ def self.documentLoader(url, validate: false, **options)
520
510
  options = OPEN_OPTS.merge(options)
521
511
  RDF::Util::File.open_file(url, options) do |remote_doc|
522
512
  content_type = remote_doc.content_type if remote_doc.respond_to?(:content_type)
523
513
  # If the passed input is a DOMString representing the IRI of a remote document, dereference it. If the retrieved document's content type is neither application/json, nor application/ld+json, nor any other media type using a +json suffix as defined in [RFC6839], reject the promise passing an loading document failed error.
524
- if content_type && options[:validate]
514
+ if content_type && validate
525
515
  main, sub = content_type.split("/")
526
516
  raise JSON::LD::JsonLdError::LoadingDocumentFailed, "url: #{url}, content_type: #{content_type}" if
527
517
  main != 'application' ||