json-ld 3.1.4 → 3.1.5

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
  SHA256:
3
- metadata.gz: 4755155aaabbcf15c3f29429eb085ac5e54c0785df8a84ebb42d8dbbb840c9b3
4
- data.tar.gz: e8f5a6fc936ee33473f8f54ae9ee1587816b3146f4c94e179eebb2ebaa85feea
3
+ metadata.gz: 65b570568511427e573b9ffecdc5eedfee1b708c62e88ffc24dce4ffa8d62c2f
4
+ data.tar.gz: a3255398de49dd88c3d4b3beb918857c8939de6eed4cf92c2aa1f61764455b59
5
5
  SHA512:
6
- metadata.gz: 8ebbbad6fde10f4ce69d8485292a580d2d9dc9cf1ffafcd878efb03a3c47bdfcd2188f1f50ec3a4d96b1a3cf7718d5926118f0283204f7420765e691d5782b78
7
- data.tar.gz: bb86cdff64bceb60c574e5a72448394c9882817990b4a734e29ab1f6bc2f177fabf2fb0437bfa5c312ca87a1f7be10123cae1bc45db8722fb1029701cb38f16c
6
+ metadata.gz: 6f84d29c4d742ffe07dbdc585f8d51e612b7426dc3a58d21061d959587ebdfff0801bc02d3c7edf11426d03d6b9d500a54bdd172afc34b460bd5957fc0f9e4c5
7
+ data.tar.gz: ee8b915d0fb258e909e751c668ea31750b255d5d7e0276123439a149eece298284324fb63a8d13df9b23109f0662dcbcd0db41f56e23e22f745da17f50f7b75b
data/README.md CHANGED
@@ -25,21 +25,25 @@ This gem implements an optimized streaming reader used for generating RDF from l
25
25
  * Keys in JSON objects must be ordered with any of `@context`, and/or `@type` coming before any other keys, in that order. This includes aliases of those keys. It is strongly encouraged that `@id` be present, and come immediately after.
26
26
  * JSON-LD documents can be signaled or requested in [streaming document form](https://w3c.github.io/json-ld-streaming/#dfn-streaming-document-form). The profile URI identifying the [streaming document form](https://w3c.github.io/json-ld-streaming/#dfn-streaming-document-form) is `http://www.w3.org/ns/json-ld#streaming`.
27
27
 
28
- ### MultiJson parser
29
- The [MultiJson](https://rubygems.org/gems/multi_json) gem is used for parsing JSON; this defaults to the native JSON parser, but will use a more performant parser if one is available. A specific parser can be specified by adding the `:adapter` option to any API call. See [MultiJson](https://rubygems.org/gems/multi_json) for more information.
30
-
31
- ### JSON-LD Streaming Profile
32
- This gem implements an optimized streaming writer used for generating JSON-LD from large repositories. Such documents result in the JSON-LD Streaming Profile:
28
+ This gem also implements an optimized streaming writer used for generating JSON-LD from large repositories. Such documents result in the JSON-LD Streaming Profile:
33
29
 
34
30
  * Each statement written as a separate node in expanded/flattened form.
35
- * RDF Lists are written as separate nodes using `rdf:first` and `rdf:rest` properties.
31
+ * `RDF List`s are written as separate nodes using `rdf:first` and `rdf:rest` properties.
32
+
33
+ The order of triples retrieved from the `RDF::Enumerable` dataset determines the way that JSON-LD node objects are written; for best results, statements should be ordered by _graph name_, _subect_, _predicate_ and _object_.
34
+
35
+ ### MultiJson parser
36
+ The [MultiJson](https://rubygems.org/gems/multi_json) gem is used for parsing JSON; this defaults to the native JSON parser, but will use a more performant parser if one is available. A specific parser can be specified by adding the `:adapter` option to any API call. See [MultiJson](https://rubygems.org/gems/multi_json) for more information.
36
37
 
37
38
  ## Examples
39
+
38
40
  ```ruby
39
41
  require 'rubygems'
40
42
  require 'json/ld'
41
43
  ```
44
+
42
45
  ### Expand a Document
46
+
43
47
  ```ruby
44
48
  input = JSON.parse %({
45
49
  "@context": {
@@ -59,8 +63,9 @@ require 'json/ld'
59
63
  "http://xmlns.com/foaf/0.1/avatar": [{"@value": "https://twitter.com/account/profile_image/manusporny"}]
60
64
  }]
61
65
  ```
66
+
62
67
  ### Compact a Document
63
- ```ruby
68
+
64
69
  input = JSON.parse %([{
65
70
  "http://xmlns.com/foaf/0.1/name": ["Manu Sporny"],
66
71
  "http://xmlns.com/foaf/0.1/homepage": [{"@id": "https://manu.sporny.org/"}],
@@ -86,9 +91,9 @@ require 'json/ld'
86
91
  "homepage": "https://manu.sporny.org/",
87
92
  "name": "Manu Sporny"
88
93
  }
89
- ```
94
+
90
95
  ### Frame a Document
91
- ```ruby
96
+
92
97
  input = JSON.parse %({
93
98
  "@context": {
94
99
  "Book": "http://example.org/vocab#Book",
@@ -169,9 +174,9 @@ require 'json/ld'
169
174
  }
170
175
  ]
171
176
  }
172
- ```
177
+
173
178
  ### Turn JSON-LD into RDF (Turtle)
174
- ```ruby
179
+
175
180
  input = JSON.parse %({
176
181
  "@context": {
177
182
  "": "https://manu.sporny.org/",
@@ -192,9 +197,9 @@ require 'json/ld'
192
197
  <http://example.org/people#joebob> a foaf:Person;
193
198
  foaf:name "Joe Bob";
194
199
  foaf:nick ("joe" "bob" "jaybe") .
195
- ```
200
+
196
201
  ### Turn RDF into JSON-LD
197
- ```ruby
202
+
198
203
  require 'rdf/turtle'
199
204
  input = RDF::Graph.new << RDF::Turtle::Reader.new(%(
200
205
  @prefix foaf: <http://xmlns.com/foaf/0.1/> .
@@ -230,11 +235,12 @@ require 'json/ld'
230
235
  "http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}]
231
236
  }
232
237
  ]
233
- ```
238
+
234
239
  ## Use a custom Document Loader
235
240
  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 (however, see [json-ld-preloaded](https://rubygems.org/gems/json-ld-preloaded)).
236
241
 
237
242
  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:
243
+
238
244
  ```ruby
239
245
  load_document_local = Proc.new do |url, **options, &block|
240
246
  if RDF::URI(url, canonicalize: true) == RDF::URI('http://schema.org/')
@@ -244,28 +250,34 @@ load_document_local = Proc.new do |url, **options, &block|
244
250
  JSON::LD::API.documentLoader(url, options, &block)
245
251
  end
246
252
  end
253
+
247
254
  ```
248
255
  Then, when performing something like expansion:
256
+
249
257
  ```ruby
250
258
  JSON::LD::API.expand(input, documentLoader: load_document_local)
251
259
  ```
252
260
 
253
261
  ## Preloading contexts
254
262
  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.
263
+
255
264
  ```ruby
256
265
  ctx = JSON::LD::Context.new().parse('http://schema.org/')
257
266
  JSON::LD::Context.add_preloaded('http://schema.org/', ctx)
258
267
  ```
268
+
259
269
  On lookup, URIs with an `https` prefix are normalized to `http`.
260
270
 
261
271
  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}.
262
272
 
263
273
  ## RDF Reader and Writer
264
274
  {JSON::LD} also acts as a normal RDF reader and writer, using the standard RDF.rb reader/writer interfaces:
275
+
265
276
  ```ruby
266
277
  graph = RDF::Graph.load("etc/doap.jsonld", format: :jsonld)
267
278
  graph.dump(:jsonld, standard_prefixes: true)
268
279
  ```
280
+
269
281
  `RDF::GRAPH#dump` can also take a `:context` option to use a separately defined context
270
282
 
271
283
  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 `]`.
@@ -275,7 +287,7 @@ This implementation is being used as a test-bed for features planned for an upco
275
287
 
276
288
  ### Scoped Contexts
277
289
  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.
278
- ```ruby
290
+
279
291
  {
280
292
  "@context": {
281
293
  "ex": "http://example.com/",
@@ -290,10 +302,10 @@ A term definition can include `@context`, which is applied to values of that obj
290
302
  },
291
303
  "foo": "Bar"
292
304
  }
293
- ```
305
+
294
306
  ### @id and @type maps
295
307
  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.
296
- ```ruby
308
+
297
309
  {
298
310
  "@context": {
299
311
  "@vocab": "http://example/",
@@ -304,10 +316,10 @@ The value of `@container` in a term definition can include `@id` or `@type`, in
304
316
  "_:bar": {"label": "Object with @id _:bar"}
305
317
  }
306
318
  }
307
- ```
319
+
308
320
  ### @graph containers and maps
309
321
  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.
310
- ```ruby
322
+
311
323
  {
312
324
  "@context": {
313
325
  "@vocab": "http://example.org/",
@@ -317,9 +329,9 @@ A term can have `@container` set to include `@graph` optionally including `@id`
317
329
  "value": "x"
318
330
  }
319
331
  }
320
- ```
332
+
321
333
  which expands to the following:
322
- ```ruby
334
+
323
335
  [{
324
336
  "http://example.org/input": [{
325
337
  "@graph": [{
@@ -327,18 +339,18 @@ which expands to the following:
327
339
  }]
328
340
  }]
329
341
  }]
330
- ```
342
+
331
343
  Compaction reverses this process, optionally ensuring that a single value is contained within an array of `@container` also includes `@set`:
332
- ```ruby
344
+
333
345
  {
334
346
  "@context": {
335
347
  "@vocab": "http://example.org/",
336
348
  "input": {"@container": ["@graph", "@set"]}
337
349
  }
338
350
  }
339
- ```
351
+
340
352
  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.
341
- ```ruby
353
+
342
354
  {
343
355
  "@context": {
344
356
  "@vocab": "http://example.org/",
@@ -348,9 +360,9 @@ A graph map uses the map form already existing for `@index`, `@language`, `@type
348
360
  "g1": {"value": "x"}
349
361
  }
350
362
  }
351
- ```
363
+
352
364
  treats "g1" as an index, and expands to the following:
353
- ```ruby
365
+
354
366
  [{
355
367
  "http://example.org/input": [{
356
368
  "@index": "g1",
@@ -359,11 +371,11 @@ treats "g1" as an index, and expands to the following:
359
371
  }]
360
372
  }]
361
373
  }])
362
- ```
374
+
363
375
  This can also include `@set` to ensure that, when compacting, a single value of an index will be in array form.
364
376
 
365
377
  The _id_ version is similar:
366
- ```ruby
378
+
367
379
  {
368
380
  "@context": {
369
381
  "@vocab": "http://example.org/",
@@ -373,9 +385,9 @@ The _id_ version is similar:
373
385
  "http://example.com/g1": {"value": "x"}
374
386
  }
375
387
  }
376
- ```
388
+
377
389
  which expands to:
378
- ```ruby
390
+
379
391
  [{
380
392
  "http://example.org/input": [{
381
393
  "@id": "http://example.com/g1",
@@ -384,10 +396,10 @@ which expands to:
384
396
  }]
385
397
  }]
386
398
  }])
387
- ```
399
+
388
400
  ### Transparent Nesting
389
401
  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:
390
- ```json
402
+
391
403
  {
392
404
  "@context": {
393
405
  "skos": "http://www.w3.org/2004/02/skos/core#",
@@ -403,9 +415,9 @@ Many JSON APIs separate properties from their entities using an intermediate obj
403
415
  "other_label": "This is the other label"
404
416
  }
405
417
  }
406
- ```
418
+
407
419
  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:
408
- ```json
420
+
409
421
  {
410
422
  "@context": {
411
423
  "skos": "http://www.w3.org/2004/02/skos/core#",
@@ -419,9 +431,9 @@ Many JSON APIs separate properties from their entities using an intermediate obj
419
431
  "main_label": "This is the main label for my resource",
420
432
  "other_label": "This is the other label"
421
433
  }
422
- ```
434
+
423
435
  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.
424
- ```json
436
+
425
437
  {
426
438
  "@context": {
427
439
  "skos": "http://www.w3.org/2004/02/skos/core#",
@@ -437,7 +449,7 @@ Many JSON APIs separate properties from their entities using an intermediate obj
437
449
  "other_label": "This is the other label"
438
450
  }
439
451
  }
440
- ```
452
+
441
453
  In this way, nesting survives round-tripping through expansion, and framed output can include nested properties.
442
454
 
443
455
  ## Sinatra/Rack support
@@ -515,14 +527,14 @@ Note, the API method signatures differed in versions before 1.0, in that they al
515
527
  ## Installation
516
528
  The recommended installation method is via [RubyGems](https://rubygems.org/).
517
529
  To install the latest official release of the `JSON-LD` gem, do:
518
- ```bash
519
- % [sudo] gem install json-ld
520
- ```
530
+
531
+ % [sudo] gem install json-ld
532
+
521
533
  ## Download
522
534
  To get a local working copy of the development repository, do:
523
- ```bash
524
- % git clone git://github.com/ruby-rdf/json-ld.git
525
- ```
535
+
536
+ % git clone git://github.com/ruby-rdf/json-ld.git
537
+
526
538
  ## Mailing List
527
539
  * <https://lists.w3.org/Archives/Public/public-rdf-ruby/>
528
540
 
@@ -540,7 +552,9 @@ To get a local working copy of the development repository, do:
540
552
  list in the the `README`. Alphabetical order applies.
541
553
  * Do note that in order for us to merge any non-trivial changes (as a rule
542
554
  of thumb, additions larger than about 15 lines of code), we need an
543
- explicit [public domain dedication][PDD] on record from you.
555
+ explicit [public domain dedication][PDD] on record from you,
556
+ which you will be asked to agree to on the first commit to a repo within the organization.
557
+ Note that the agreement applies to all repos in the [Ruby RDF](https://github.com/ruby-rdf/) organization.
544
558
 
545
559
  License
546
560
  -------
@@ -552,7 +566,7 @@ see <https://unlicense.org/> or the accompanying {file:UNLICENSE} file.
552
566
  [RDF]: https://www.w3.org/RDF/
553
567
  [YARD]: https://yardoc.org/
554
568
  [YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md
555
- [PDD]: https://lists.w3.org/Archives/Public/public-rdf-ruby/2010May/0013.html
569
+ [PDD]: https://unlicense.org/#unlicensing-contributions
556
570
  [RDF.rb]: https://rubygems.org/gems/rdf
557
571
  [Rack::LinkedData]: https://rubygems.org/gems/rack-linkeddata
558
572
  [Backports]: https://rubygems.org/gems/backports
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.4
1
+ 3.1.5
data/bin/jsonld CHANGED
@@ -10,7 +10,7 @@ require 'getoptlong'
10
10
  require 'open-uri'
11
11
  require 'logger'
12
12
 
13
- def run(input, options)
13
+ def run(input, options, parser_options)
14
14
  reader_class = RDF::Reader.for(options[:input_format].to_sym)
15
15
  raise "Reader not found for #{options[:input_format]}" unless reader_class
16
16
 
@@ -19,38 +19,38 @@ def run(input, options)
19
19
 
20
20
  # If input format is not JSON-LD, transform input to JSON-LD first
21
21
  reader = if options[:input_format] != :jsonld
22
- reader_class.new(input, options[:parser_options])
22
+ reader_class.new(input, parser_options)
23
23
  end
24
24
 
25
25
  start = Time.new
26
26
  if options[:expand]
27
- options = options.merge(expandContext: options.delete(:context)) if options.has_key?(:context)
27
+ parser_options = parser_options.merge(expandContext: parser_options.delete(:context)) if parser_options.has_key?(:context)
28
28
  input = JSON::LD::API.fromRdf(reader) if reader
29
- output = JSON::LD::API.expand(input, options)
29
+ output = JSON::LD::API.expand(input, parser_options)
30
30
  secs = Time.new - start
31
31
  options[:output].puts output.to_json(JSON::LD::JSON_STATE)
32
32
  STDERR.puts "Expanded in #{secs} seconds." unless options[:quiet]
33
33
  elsif options[:compact]
34
34
  input = JSON::LD::API.fromRdf(reader) if reader
35
- output = JSON::LD::API.compact(input, options[:context], options)
35
+ output = JSON::LD::API.compact(input, parser_options[:context], parser_options)
36
36
  secs = Time.new - start
37
37
  options[:output].puts output.to_json(JSON::LD::JSON_STATE)
38
38
  STDERR.puts "Compacted in #{secs} seconds." unless options[:quiet]
39
39
  elsif options[:flatten]
40
40
  input = JSON::LD::API.fromRdf(reader) if reader
41
- output = JSON::LD::API.flatten(input, options[:context], options)
41
+ output = JSON::LD::API.flatten(input, parser_options[:context], parser_options)
42
42
  secs = Time.new - start
43
43
  options[:output].puts output.to_json(JSON::LD::JSON_STATE)
44
44
  STDERR.puts "Flattened in #{secs} seconds." unless options[:quiet]
45
45
  elsif options[:frame]
46
46
  input = JSON::LD::API.fromRdf(reader) if reader
47
- output = JSON::LD::API.frame(input, options[:frame], options)
47
+ output = JSON::LD::API.frame(input, parser_options[:frame], parser_options)
48
48
  secs = Time.new - start
49
49
  options[:output].puts output.to_json(JSON::LD::JSON_STATE)
50
50
  STDERR.puts "Framed in #{secs} seconds." unless options[:quiet]
51
51
  else
52
- options = options.merge(expandContext: options.delete(:context)) if options.has_key?(:context)
53
- parser_options = options[:parser_options].merge(standard_prefixes: true)
52
+ parser_options = parser_options.merge(expandContext: parser_options.delete(:context)) if parser_options.has_key?(:context)
53
+ parser_options[:standard_prefixes] = true
54
54
  reader ||= JSON::LD::Reader.new(input, parser_options)
55
55
  num = 0
56
56
  RDF::Writer.for(options[:output_format]).new(options[:output], parser_options) do |w|
@@ -86,7 +86,6 @@ parser_options = {
86
86
  }
87
87
 
88
88
  options = {
89
- parser_options: parser_options,
90
89
  output: STDOUT,
91
90
  output_format: :jsonld,
92
91
  input_format: :jsonld,
@@ -141,49 +140,47 @@ opts = GetoptLong.new(*OPT_ARGS.map {|o| o[0..-2]})
141
140
  opts.each do |opt, arg|
142
141
  case opt
143
142
  when '--debug' then logger.level = Logger::DEBUG
144
- when '--compact' then options[:compact] = true
145
- when "--compactArrays" then options[:compactArrays] = (arg || 'true') == 'true'
146
- when '--context' then options[:context] = arg
143
+ when '--compact' then parser_options[:compact] = true
144
+ when "--compactArrays" then parser_options[:compactArrays] = (arg || 'true') == 'true'
145
+ when '--context' then parser_options[:context] = RDF::URI(arg).absolute? ? arg : File.open(arg)
147
146
  when '--evaluate' then input = arg
148
147
  when '--expand' then options[:expand] = true
149
- when "--expanded" then options[:expanded] = (arg || 'true') == 'true'
150
- when "--explicit" then options[:compactArrays] = (arg || 'true') == 'true'
148
+ when "--expanded" then parser_options[:expanded] = (arg || 'true') == 'true'
149
+ when "--explicit" then parser_options[:compactArrays] = (arg || 'true') == 'true'
151
150
  when '--format' then options[:output_format] = arg.to_sym
152
151
  when '--flatten' then options[:flatten] = arg
153
- when '--frame' then options[:frame] = arg
152
+ when '--frame' then options[:frame] = parser_otpions[:frame] = RDF::URI(arg).absolute? ? arg : File.open(arg)
154
153
  when '--input-format' then options[:input_format] = arg.to_sym
155
- when "--omitDefault" then options[:omitDefault] = (arg || 'true') == 'true'
154
+ when "--omitDefault" then parser_options[:omitDefault] = (arg || 'true') == 'true'
156
155
  when '--output' then options[:output] = File.open(arg, "w")
157
156
  when '--parse-only' then options[:parse_only] = true
158
- when '--processingMode' then options[:processingMode] = arg
157
+ when '--processingMode' then parser_options[:processingMode] = arg
159
158
  when '--quiet'
160
159
  options[:quiet] = true
161
160
  logger.level = Logger::FATAL
162
- when "--rename_bnodes" then options[:rename_bnodes] = (arg || 'true') == 'true'
163
- when "--requireAll" then options[:requireAll] = (arg || 'true') == 'true'
161
+ when "--rename_bnodes" then parser_options[:rename_bnodes] = (arg || 'true') == 'true'
162
+ when "--requireAll" then parser_options[:requireAll] = (arg || 'true') == 'true'
164
163
  when '--stream' then parser_options[:stream] = true
165
- when "--unique_bnodes" then options[:unique_bnodes] = (arg || 'true') == 'true'
164
+ when "--unique_bnodes" then parser_options[:unique_bnodes] = (arg || 'true') == 'true'
166
165
  when '--uri' then parser_options[:base] = arg
167
166
  when '--validate' then parser_options[:validate] = true
168
167
  when '--help' then usage
169
168
  when '--embed'
170
169
  case arg
171
- when '@always', '@never', '@link', '@last', '@first'
172
- options[:embed] = arg
170
+ when '@always', '@never', '@link', '@once'
171
+ parser_options[:embed] = arg
173
172
  when 'true'
174
- options[:embed] = '@never'
173
+ parser_options[:embed] = '@never'
175
174
  when 'false'
176
- options[:embed] = '@first'
175
+ parser_options[:embed] = '@first'
177
176
  else
178
- STDERR.puts "--embed option takes one of @always, @never, @link, @first, or @last"
177
+ STDERR.puts "--embed option takes one of @always, @never, @link, or @once"
179
178
  exit(1)
180
179
  end
181
180
  end
182
181
  end
183
182
 
184
183
  # Hack
185
- options[:parser_options][:context] = options[:context] if parser_options[:stream]
186
-
187
184
  if !(options.keys & [:expand, :compact, :flatten, :frame]).empty? &&
188
185
  (parser_options[:stream] || options[:output_format] != :jsonld)
189
186
  STDERR.puts "Incompatible options"
@@ -192,11 +189,11 @@ end
192
189
 
193
190
  if ARGV.empty?
194
191
  s = input ? input : $stdin.read
195
- run(StringIO.new(s), options)
192
+ run(StringIO.new(s), options, parser_options)
196
193
  else
197
194
  ARGV.each do |file|
198
195
  # Call with opened files
199
- RDF::Util::File.open_file(file, options) {|f| run(f, options)}
196
+ RDF::Util::File.open_file(file, options) {|f| run(f, options, parser_options)}
200
197
  end
201
198
  end
202
199
  puts
@@ -1,7 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # frozen_string_literal: true
3
3
  $:.unshift(File.expand_path("../ld", __FILE__))
4
- require 'rdf' # @see http://rubygems.org/gems/rdf
4
+ require 'rdf' # @see https://rubygems.org/gems/rdf
5
5
  require 'multi_json'
6
6
  require 'set'
7
7
 
@@ -19,7 +19,7 @@ module JSON
19
19
  # end
20
20
  # end
21
21
  #
22
- # @see http://rubygems.org/gems/rdf
22
+ # @see https://rubygems.org/gems/rdf
23
23
  # @see http://www.w3.org/TR/REC-rdf-syntax/
24
24
  #
25
25
  # @author [Gregg Kellogg](http://greggkellogg.net/)
@@ -19,12 +19,9 @@ module JSON::LD
19
19
  # @return [Array, Hash]
20
20
  def compact(element,
21
21
  base: nil,
22
- property: nil)
23
- #if property.nil?
24
- # log_debug("compact") {"element: #{element.inspect}, ec: #{context.inspect}"}
25
- #else
26
- # log_debug("compact") {"property: #{property.inspect}"}
27
- #end
22
+ property: nil,
23
+ log_depth: nil)
24
+ log_debug("compact", depth: log_depth.to_i) {"element: #{element.inspect}, ec: #{context.inspect}"}
28
25
 
29
26
  # If the term definition for active property itself contains a context, use that for compacting values.
30
27
  input_context = self.context
@@ -33,7 +30,7 @@ module JSON::LD
33
30
  when Array
34
31
  #log_debug("") {"Array #{element.inspect}"}
35
32
  result = element.map do |item|
36
- compact(item, base: base, property: property)
33
+ compact(item, base: base, property: property, log_depth: log_depth.to_i + 1)
37
34
  end.compact
38
35
 
39
36
  # If element has a single member and the active property has no
@@ -41,10 +38,10 @@ module JSON::LD
41
38
  # member; otherwise the compacted value is element
42
39
  if result.length == 1 &&
43
40
  !context.as_array?(property) && @options[:compactArrays]
44
- #log_debug("=> extract single element: #{result.first.inspect}")
41
+ log_debug("=> extract single element", depth: log_depth.to_i) {result.first.inspect}
45
42
  result.first
46
43
  else
47
- #log_debug("=> array result: #{result.inspect}")
44
+ log_debug("=> array result", depth: log_depth.to_i) {result.inspect}
48
45
  result
49
46
  end
50
47
  when Hash
@@ -55,6 +52,7 @@ module JSON::LD
55
52
 
56
53
  # Revert any previously type-scoped (non-preserved) context
57
54
  if context.previous_context && !element.key?('@value') && element.keys != %w(@id)
55
+ log_debug("revert ec", depth: log_depth.to_i) {"previous context: #{context.previous_context.inspect}"}
58
56
  self.context = context.previous_context
59
57
  end
60
58
 
@@ -63,12 +61,13 @@ module JSON::LD
63
61
  if td && !td.context.nil?
64
62
  self.context = context.parse(td.context,
65
63
  override_protected: true)
64
+ log_debug("prop-scoped", depth: log_depth.to_i) {"context: #{self.context.inspect}"}
66
65
  end
67
66
 
68
67
  if element.key?('@id') || element.key?('@value')
69
68
  result = context.compact_value(property, element, base: @options[:base])
70
69
  if !result.is_a?(Hash) || context.coerce(property) == '@json'
71
- #log_debug("") {"=> scalar result: #{result.inspect}"}
70
+ log_debug("", depth: log_depth.to_i) {"=> scalar result: #{result.inspect}"}
72
71
  return result
73
72
  end
74
73
  end
@@ -76,7 +75,8 @@ module JSON::LD
76
75
  # If expanded property is @list and we're contained within a list container, recursively compact this item to an array
77
76
  if list?(element) && context.container(property).include?('@list')
78
77
  return compact(element['@list'], base: base,
79
- property: property)
78
+ property: property,
79
+ log_depth: log_depth.to_i + 1)
80
80
  end
81
81
 
82
82
  inside_reverse = property == '@reverse'
@@ -90,11 +90,12 @@ module JSON::LD
90
90
  each do |term|
91
91
  term_context = input_context.term_definitions[term].context if input_context.term_definitions[term]
92
92
  self.context = context.parse(term_context, propagate: false) unless term_context.nil?
93
+ log_debug("type-scoped", depth: log_depth.to_i) {"context: #{self.context.inspect}"}
93
94
  end
94
95
 
95
96
  element.keys.opt_sort(ordered: @options[:ordered]).each do |expanded_property|
96
97
  expanded_value = element[expanded_property]
97
- #log_debug("") {"#{expanded_property}: #{expanded_value.inspect}"}
98
+ log_debug("", depth: log_depth.to_i) {"#{expanded_property}: #{expanded_value.inspect}"}
98
99
 
99
100
  if expanded_property == '@id'
100
101
  compacted_value = Array(expanded_value).map do |expanded_id|
@@ -124,8 +125,9 @@ module JSON::LD
124
125
 
125
126
  if expanded_property == '@reverse'
126
127
  compacted_value = compact(expanded_value, base: base,
127
- property: '@reverse')
128
- #log_debug("@reverse") {"compacted_value: #{compacted_value.inspect}"}
128
+ property: '@reverse',
129
+ log_depth: log_depth.to_i + 1)
130
+ log_debug("@reverse", depth: log_depth.to_i) {"compacted_value: #{compacted_value.inspect}"}
129
131
  # handle double-reversed properties
130
132
  compacted_value.each do |prop, value|
131
133
  if context.reverse?(prop)
@@ -137,7 +139,7 @@ module JSON::LD
137
139
 
138
140
  unless compacted_value.empty?
139
141
  al = context.compact_iri('@reverse')
140
- #log_debug("") {"remainder: #{al} => #{compacted_value.inspect}"}
142
+ log_debug("", depth: log_depth.to_i) {"remainder: #{al} => #{compacted_value.inspect}"}
141
143
  result[al] = compacted_value
142
144
  end
143
145
  next
@@ -146,8 +148,9 @@ module JSON::LD
146
148
  if expanded_property == '@preserve'
147
149
  # Compact using `property`
148
150
  compacted_value = compact(expanded_value, base: base,
149
- property: property)
150
- #log_debug("@preserve") {"compacted_value: #{compacted_value.inspect}"}
151
+ property: property,
152
+ log_depth: log_depth.to_i + 1)
153
+ log_debug("@preserve", depth: log_depth.to_i) {"compacted_value: #{compacted_value.inspect}"}
151
154
 
152
155
  unless compacted_value.is_a?(Array) && compacted_value.empty?
153
156
  result['@preserve'] = compacted_value
@@ -156,14 +159,14 @@ module JSON::LD
156
159
  end
157
160
 
158
161
  if expanded_property == '@index' && context.container(property).include?('@index')
159
- #log_debug("@index") {"drop @index"}
162
+ log_debug("@index", depth: log_depth.to_i) {"drop @index"}
160
163
  next
161
164
  end
162
165
 
163
166
  # Otherwise, if expanded property is @direction, @index, @value, or @language:
164
167
  if EXPANDED_PROPERTY_DIRECTION_INDEX_LANGUAGE_VALUE.include?(expanded_property)
165
168
  al = context.compact_iri(expanded_property, vocab: true)
166
- #log_debug(expanded_property) {"#{al} => #{expanded_value.inspect}"}
169
+ log_debug(expanded_property, depth: log_depth.to_i) {"#{al} => #{expanded_value.inspect}"}
167
170
  result[al] = expanded_value
168
171
  next
169
172
  end
@@ -211,8 +214,9 @@ module JSON::LD
211
214
  end
212
215
 
213
216
  compacted_item = compact(value, base: base,
214
- property: item_active_property)
215
- #log_debug("") {" => compacted key: #{item_active_property.inspect} for #{compacted_item.inspect}"}
217
+ property: item_active_property,
218
+ log_depth: log_depth.to_i + 1)
219
+ log_debug("", depth: log_depth.to_i) {" => compacted key: #{item_active_property.inspect} for #{compacted_item.inspect}"}
216
220
 
217
221
  # handle @list
218
222
  if list?(expanded_item)
@@ -315,7 +319,8 @@ module JSON::LD
315
319
  if compacted_item.keys.length == 1 && expanded_item.keys.include?('@id')
316
320
  compacted_item = compact({'@id' => expanded_item['@id']},
317
321
  base: base,
318
- property: item_active_property)
322
+ property: item_active_property,
323
+ log_depth: log_depth.to_i + 1)
319
324
  end
320
325
  compacted_item
321
326
  end
@@ -332,7 +337,7 @@ module JSON::LD
332
337
  result
333
338
  else
334
339
  # For other types, the compacted value is the element value
335
- #log_debug("compact") {element.class.to_s}
340
+ log_debug("compact", depth: log_depth.to_i) {element.class.to_s}
336
341
  element
337
342
  end
338
343
 
@@ -46,7 +46,7 @@ module JSON::LD
46
46
  #
47
47
  # @param [Hash{String => String}] env
48
48
  # @return [Array(Integer, Hash, #each)] Status, Headers and Body
49
- # @see http://rack.rubyforge.org/doc/SPEC.html
49
+ # @see https://rubydoc.info/github/rack/rack/file/SPEC
50
50
  def call(env)
51
51
  response = app.call(env)
52
52
  body = response[2].respond_to?(:body) ? response[2].body : response[2]
@@ -104,16 +104,12 @@ module JSON::LD
104
104
  # @see #initialize
105
105
  # @see #parse
106
106
  # @param [String, #read, Array, Hash, Context] local_context
107
- # @param [String, #to_s] :base (nil)
107
+ # @param [String, #to_s] base (nil)
108
108
  # The Base IRI to use when expanding the document. This overrides the value of `input` if it is a _IRI_. If not specified and `input` is not an _IRI_, the base IRI defaults to the current document IRI if in a browser context, or the empty string if there is no document context.
109
- # @param [Proc] :documentLoader (nil)
110
- # The callback of the loader to be used to retrieve remote documents and contexts. If specified, it must be used to retrieve remote documents and contexts; otherwise, if not specified, the processor's built-in loader must be used. See {API.documentLoader} for the method signature.
111
109
  # @param [Boolean] override_protected (false)
112
110
  # Protected terms may be cleared.
113
111
  # @param [Boolean] propagate (true)
114
112
  # If false, retains any previously defined term, which can be rolled back when the descending into a new node object changes.
115
- # @param [Boolean] validate (false)
116
- # Extra validatation
117
113
  # @raise [JsonLdError]
118
114
  # on a remote context load error, syntax error, or a reference to a term which is not defined.
119
115
  # @return [Context]
@@ -231,14 +227,12 @@ module JSON::LD
231
227
  #
232
228
  #
233
229
  # @param [String, #read, Array, Hash, Context] local_context
234
- # @param [String, #to_s] :base
230
+ # @param [String, #to_s] base
235
231
  # The Base IRI to use when expanding the document. This overrides the value of `input` if it is a _IRI_. If not specified and `input` is not an _IRI_, the base IRI defaults to the current document IRI if in a browser context, or the empty string if there is no document context.
236
232
  # @param [Boolean] override_protected Protected terms may be cleared.
237
233
  # @param [Boolean] propagate (true)
238
234
  # If false, retains any previously defined term, which can be rolled back when the descending into a new node object changes.
239
235
  # @param [Array<String>] remote_contexts ([])
240
- # @param [Boolean] validate (false)
241
- # Extra validatation
242
236
  # @param [Boolean] validate_scoped (true).
243
237
  # Validate scoped context, loading if necessary.
244
238
  # If false, do not load scoped contexts.
@@ -419,9 +413,7 @@ module JSON::LD
419
413
  # Merge in a context, creating a new context with updates from `context`
420
414
  #
421
415
  # @param [Context] context
422
- # @param [Boolean] protected mark resulting context as protected
423
416
  # @param [Boolean] override_protected Allow or disallow protected terms to be changed
424
- # @param [Boolean]
425
417
  # @return [Context]
426
418
  def merge(context, override_protected: false)
427
419
  ctx = Context.new(term_definitions: self.term_definitions, standard_prefixes: options[:standard_prefixes])
@@ -469,8 +461,6 @@ module JSON::LD
469
461
  # @param [String, RDF::URI] base for resolving document-relative IRIs
470
462
  # @param [Boolean] protected if true, causes all terms to be marked protected
471
463
  # @param [Boolean] override_protected Protected terms may be cleared.
472
- # @param [Boolean] propagate
473
- # Context is propagated across node objects.
474
464
  # @param [Array<String>] remote_contexts
475
465
  # @param [Boolean] validate_scoped (true).
476
466
  # Validate scoped context, loading if necessary.
@@ -846,7 +836,7 @@ module JSON::LD
846
836
  # If contex has a @version member, it's value MUST be 1.1, otherwise an "invalid @version value" has been detected, and processing is aborted.
847
837
  # If processingMode has been set, and it is not "json-ld-1.1", a "processing mode conflict" has been detecting, and processing is aborted.
848
838
  #
849
- # @param [String, Number] expected
839
+ # @param [String, Number] value
850
840
  # @return [String]
851
841
  # @raise [JsonLdError::ProcessingModeConflict]
852
842
  def processingMode=(value = nil, **options)
@@ -2064,7 +2054,7 @@ module JSON::LD
2064
2054
  # @param ["ltr", "rtl"] direction_mapping
2065
2055
  # Direction mapping of term, `false` is used if there is an explicit direction mapping for this term
2066
2056
  # @param [Boolean] reverse_property
2067
- # @param [Boolean] protected
2057
+ # @param [Boolean] protected mark resulting context as protected
2068
2058
  # @param [String] nest term used for nest properties
2069
2059
  # @param [Boolean] simple
2070
2060
  # This is a simple term definition, not an expanded term definition
@@ -146,9 +146,16 @@ module JSON::LD
146
146
  # Otherwise, if the value of result's @value member is not a string and result contains the key @language, an invalid language-tagged value error has been detected (only strings can be language-tagged) and processing is aborted.
147
147
  raise JsonLdError::InvalidLanguageTaggedValue,
148
148
  "when @language is used, @value must be a string: #{output_object.inspect}"
149
- elsif !Array(output_object['@type']).all? {|t|
150
- t.is_a?(String) && RDF::URI(t).valid? && !t.start_with?('_:') ||
151
- t.is_a?(Hash) && t.empty?}
149
+ elsif output_object['@type'] &&
150
+ (!Array(output_object['@type']).all? {|t|
151
+ t.is_a?(String) && RDF::URI(t).valid? && !t.start_with?('_:') ||
152
+ t.is_a?(Hash) && t.empty?} ||
153
+ !framing && !output_object['@type'].is_a?(String))
154
+ # Otherwise, if the result has a @type member and its value is not an IRI, an invalid typed value error has been detected and processing is aborted.
155
+ raise JsonLdError::InvalidTypedValue,
156
+ "value of @type must be an IRI or '@json': #{output_object.inspect}"
157
+ elsif !framing && !output_object.fetch('@type', '').is_a?(String) &&
158
+ RDF::URI(t).valid? && !t.start_with?('_:')
152
159
  # Otherwise, if the result has a @type member and its value is not an IRI, an invalid typed value error has been detected and processing is aborted.
153
160
  raise JsonLdError::InvalidTypedValue,
154
161
  "value of @type must be an IRI or '@json': #{output_object.inspect}"
@@ -58,9 +58,10 @@ module JSON::LD
58
58
  out = options[:output] || $stdout
59
59
  out.set_encoding(Encoding::UTF_8) if RUBY_PLATFORM == "java"
60
60
  options = options.merge(expandContext: options.delete(:context)) if options.has_key?(:context)
61
+ options[:base] ||= options[:base_uri]
61
62
  if options[:format] == :jsonld
62
63
  if files.empty?
63
- # If files are empty, either use options[:execute]
64
+ # If files are empty, either use options[:evaluate] or STDIN
64
65
  input = options[:evaluate] ? StringIO.new(options[:evaluate]) : STDIN
65
66
  input.set_encoding(options.fetch(:encoding, Encoding::UTF_8))
66
67
  JSON::LD::API.expand(input, validate: false, **options) do |expanded|
@@ -93,9 +94,10 @@ module JSON::LD
93
94
  raise ArgumentError, "Compacting requires a context" unless options[:context]
94
95
  out = options[:output] || $stdout
95
96
  out.set_encoding(Encoding::UTF_8) if RUBY_PLATFORM == "java"
97
+ options[:base] ||= options[:base_uri]
96
98
  if options[:format] == :jsonld
97
99
  if files.empty?
98
- # If files are empty, either use options[:execute]
100
+ # If files are empty, either use options[:evaluate] or STDIN
99
101
  input = options[:evaluate] ? StringIO.new(options[:evaluate]) : STDIN
100
102
  input.set_encoding(options.fetch(:encoding, Encoding::UTF_8))
101
103
  JSON::LD::API.compact(input, options[:context], **options) do |compacted|
@@ -126,7 +128,7 @@ module JSON::LD
126
128
  control: :url2,
127
129
  use: :required,
128
130
  on: ["--context CONTEXT"],
129
- description: "Context to use when compacting.") {|arg| RDF::URI(arg)},
131
+ description: "Context to use when compacting.") {|arg| RDF::URI(arg).absolute? ? RDF::URI(arg) : StringIO.new(File.read(arg))},
130
132
  ]
131
133
  },
132
134
  flatten: {
@@ -137,9 +139,10 @@ module JSON::LD
137
139
  lambda: ->(files, **options) do
138
140
  out = options[:output] || $stdout
139
141
  out.set_encoding(Encoding::UTF_8) if RUBY_PLATFORM == "java"
142
+ options[:base] ||= options[:base_uri]
140
143
  if options[:format] == :jsonld
141
144
  if files.empty?
142
- # If files are empty, either use options[:execute]
145
+ # If files are empty, either use options[:evaluate] or STDIN
143
146
  input = options[:evaluate] ? StringIO.new(options[:evaluate]) : STDIN
144
147
  input.set_encoding(options.fetch(:encoding, Encoding::UTF_8))
145
148
  JSON::LD::API.flatten(input, options[:context], **options) do |flattened|
@@ -173,9 +176,10 @@ module JSON::LD
173
176
  raise ArgumentError, "Framing requires a frame" unless options[:frame]
174
177
  out = options[:output] || $stdout
175
178
  out.set_encoding(Encoding::UTF_8) if RUBY_PLATFORM == "java"
179
+ options[:base] ||= options[:base_uri]
176
180
  if options[:format] == :jsonld
177
181
  if files.empty?
178
- # If files are empty, either use options[:execute]
182
+ # If files are empty, either use options[:evaluate] or STDIN
179
183
  input = options[:evaluate] ? StringIO.new(options[:evaluate]) : STDIN
180
184
  input.set_encoding(options.fetch(:encoding, Encoding::UTF_8))
181
185
  JSON::LD::API.frame(input, options[:frame], **options) do |framed|
@@ -207,7 +211,7 @@ module JSON::LD
207
211
  control: :url2,
208
212
  use: :required,
209
213
  on: ["--frame FRAME"],
210
- description: "Frame to use when serializing.") {|arg| RDF::URI(arg)}
214
+ description: "Frame to use when serializing.") {|arg| RDF::URI(arg).absolute? ? RDF::URI(arg) : StringIO.new(File.read(arg))}
211
215
  ]
212
216
  },
213
217
  }
@@ -20,7 +20,7 @@ module JSON::LD
20
20
  control: :url2,
21
21
  datatype: RDF::URI,
22
22
  on: ["--expand-context CONTEXT"],
23
- description: "Context to use when expanding.") {|arg| RDF::URI(arg)},
23
+ description: "Context to use when expanding.") {|arg| RDF::URI(arg).absolute? ? RDF::URI(arg) : StringIO.new(File.read(arg))},
24
24
  RDF::CLI::Option.new(
25
25
  symbol: :extractAllScripts,
26
26
  datatype: TrueClass,
@@ -93,7 +93,7 @@ module JSON::LD
93
93
  datatype: RDF::URI,
94
94
  control: :url2,
95
95
  on: ["--context CONTEXT"],
96
- description: "Context to use when compacting.") {|arg| RDF::URI(arg)},
96
+ description: "Context to use when compacting.") {|arg| RDF::URI(arg).absolute? ? RDF::URI(arg) : StringIO.new(File.read(arg))},
97
97
  RDF::CLI::Option.new(
98
98
  symbol: :embed,
99
99
  datatype: %w(@always @once @never),
@@ -107,6 +107,13 @@ module JSON::LD
107
107
  control: :checkbox,
108
108
  on: ["--[no-]explicit"],
109
109
  description: "Only include explicitly declared properties in output (false)") {|arg| arg},
110
+ RDF::CLI::Option.new(
111
+ symbol: :frame,
112
+ datatype: RDF::URI,
113
+ control: :url2,
114
+ use: :required,
115
+ on: ["--frame FRAME"],
116
+ description: "Frame to use when serializing.") {|arg| RDF::URI(arg).absolute? ? RDF::URI(arg) : StringIO.new(File.read(arg))},
110
117
  RDF::CLI::Option.new(
111
118
  symbol: :lowercaseLanguage,
112
119
  datatype: TrueClass,
@@ -137,7 +144,7 @@ module JSON::LD
137
144
  default: 'null',
138
145
  control: :select,
139
146
  on: ["--rdf-direction DIR", %w(i18n-datatype compound-literal)],
140
- description: "How to serialize literal direction (i18n-datatype compound-literal)") {|arg| RDF::URI(arg)},
147
+ description: "How to serialize literal direction (i18n-datatype compound-literal)") {|arg| arg},
141
148
  RDF::CLI::Option.new(
142
149
  symbol: :requireAll,
143
150
  datatype: TrueClass,
@@ -202,7 +209,7 @@ module JSON::LD
202
209
  end
203
210
 
204
211
  ##
205
- # Initializes the RDF-LD writer instance.
212
+ # Initializes the JSON-LD writer instance.
206
213
  #
207
214
  # @param [IO, File] output
208
215
  # the output stream
@@ -1,4 +1,4 @@
1
- require 'rspec/matchers' # @see http://rubygems.org/gems/rspec
1
+ require 'rspec/matchers' # @see https://rubygems.org/gems/rspec
2
2
  require_relative 'support/extensions'
3
3
 
4
4
  RSpec::Matchers.define :produce_jsonld do |expected, logger|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json-ld
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.4
4
+ version: 3.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregg Kellogg
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-28 00:00:00.000000000 Z
11
+ date: 2020-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdf
@@ -411,7 +411,7 @@ homepage: https://github.com/ruby-rdf/json-ld
411
411
  licenses:
412
412
  - Unlicense
413
413
  metadata: {}
414
- post_install_message:
414
+ post_install_message:
415
415
  rdoc_options: []
416
416
  require_paths:
417
417
  - lib
@@ -426,8 +426,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
426
426
  - !ruby/object:Gem::Version
427
427
  version: '0'
428
428
  requirements: []
429
- rubygems_version: 3.1.2
430
- signing_key:
429
+ rubygems_version: 3.1.4
430
+ signing_key:
431
431
  specification_version: 4
432
432
  summary: JSON-LD reader/writer for Ruby.
433
433
  test_files: