json-ld 3.1.4 → 3.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +131 -48
- data/VERSION +1 -1
- data/bin/jsonld +31 -32
- data/lib/json/ld.rb +5 -2
- data/lib/json/ld/api.rb +35 -16
- data/lib/json/ld/compact.rb +41 -29
- data/lib/json/ld/conneg.rb +1 -1
- data/lib/json/ld/context.rb +51 -59
- data/lib/json/ld/expand.rb +72 -16
- data/lib/json/ld/extensions.rb +4 -4
- data/lib/json/ld/flatten.rb +137 -9
- data/lib/json/ld/format.rb +28 -8
- data/lib/json/ld/frame.rb +8 -8
- data/lib/json/ld/from_rdf.rb +46 -16
- data/lib/json/ld/reader.rb +2 -1
- data/lib/json/ld/streaming_reader.rb +5 -5
- data/lib/json/ld/streaming_writer.rb +4 -4
- data/lib/json/ld/to_rdf.rb +11 -7
- data/lib/json/ld/utils.rb +13 -13
- data/lib/json/ld/writer.rb +12 -5
- data/spec/api_spec.rb +1 -1
- data/spec/compact_spec.rb +207 -3
- data/spec/context_spec.rb +0 -2
- data/spec/expand_spec.rb +631 -0
- data/spec/flatten_spec.rb +517 -1
- data/spec/from_rdf_spec.rb +181 -0
- data/spec/matchers.rb +1 -1
- data/spec/rdfstar_spec.rb +25 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/suite_flatten_spec.rb +4 -0
- data/spec/suite_frame_spec.rb +7 -0
- data/spec/suite_helper.rb +13 -7
- data/spec/suite_to_rdf_spec.rb +1 -0
- data/spec/to_rdf_spec.rb +209 -3
- data/spec/writer_spec.rb +193 -0
- metadata +66 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d6d6a64b4f09b881332fe9b54bd2c1d0ad116d590bd457443831ccc5fae3ea9
|
4
|
+
data.tar.gz: 91deee18963670cb94360b5c278dc7a8ae55ccbd897c580a54d291f1f98cfd15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f96e6b68f363ccd0b96035a66c438ff59801162742fb1b7fd6443684ee2539d34a994f01c95d9019ae46732efdd9eca37539c837af8137efa2fefb9db0930e0f
|
7
|
+
data.tar.gz: 5fe42b5836c6620aa3b485b2622ef94c7d73c63ec3de495779520c697201cdcd2ae4920e3b210f19cc49523e6b1a02b6b73482bc3fc23b7bb9717ba7cd50f04b
|
data/README.md
CHANGED
@@ -2,9 +2,10 @@
|
|
2
2
|
|
3
3
|
[JSON-LD][] reader/writer for [RDF.rb][RDF.rb] and fully conforming [JSON-LD API][] processor. Additionally this gem implements [JSON-LD Framing][].
|
4
4
|
|
5
|
-
[](https://
|
6
|
-
[](https://coveralls.io/
|
5
|
+
[](https://rubygems.org/gems/json-ld)
|
6
|
+
[](https://github.com/ruby-rdf/json-ld/actions?query=workflow%3ACI)
|
7
|
+
[](https://coveralls.io/github/ruby-rdf/json-ld?branch=develop)
|
8
|
+
[](https://gitter.im/gitterHQ/gitter)
|
8
9
|
|
9
10
|
## Features
|
10
11
|
|
@@ -14,8 +15,9 @@ JSON::LD can now be used to create a _context_ from an RDFS/OWL definition, and
|
|
14
15
|
|
15
16
|
* If the [jsonlint][] gem is installed, it will be used when validating an input document.
|
16
17
|
* If available, uses [Nokogiri][] and/or [Nokogumbo][] for parsing HTML, falls back to REXML otherwise.
|
18
|
+
* Provisional support for [JSON-LD-star][JSON-LD-star].
|
17
19
|
|
18
|
-
[Implementation Report](
|
20
|
+
[Implementation Report](https://ruby-rdf.github.io/json-ld/etc/earl.html)
|
19
21
|
|
20
22
|
Install with `gem install json-ld`
|
21
23
|
|
@@ -25,21 +27,91 @@ This gem implements an optimized streaming reader used for generating RDF from l
|
|
25
27
|
* 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
28
|
* 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
29
|
|
30
|
+
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:
|
31
|
+
|
32
|
+
* Each statement written as a separate node in expanded/flattened form.
|
33
|
+
* `RDF List`s are written as separate nodes using `rdf:first` and `rdf:rest` properties.
|
34
|
+
|
35
|
+
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_.
|
36
|
+
|
28
37
|
### MultiJson parser
|
29
38
|
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
39
|
|
31
|
-
### JSON-LD
|
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:
|
40
|
+
### JSON-LD-star (RDFStar)
|
33
41
|
|
34
|
-
|
35
|
-
|
42
|
+
The {JSON::LD::API.expand}, {JSON::LD::API.compact}, {JSON::LD::API.toRdf}, and {JSON::LD::API.fromRdf} API methods, along with the {JSON::LD::Reader} and {JSON::LD::Writer}, include provisional support for [JSON-LD-star][JSON-LD-star].
|
43
|
+
|
44
|
+
Internally, an `RDF::Statement` is treated as another resource, along with `RDF::URI` and `RDF::Node`, which allows an `RDF::Statement` to have a `#subject` or `#object` which is also an `RDF::Statement`.
|
45
|
+
|
46
|
+
In JSON-LD, with the `rdfstar` option set, the value of `@id`, in addition to an IRI or Blank Node Identifier, can be a JSON-LD node object having exactly one property with an optional `@id`, which may also be an embedded object. (It may also have `@context` and `@index` values).
|
47
|
+
|
48
|
+
{
|
49
|
+
"@id": {
|
50
|
+
"@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
|
51
|
+
"@index": "ignored",
|
52
|
+
"@id": "bob",
|
53
|
+
"foaf:age" 23
|
54
|
+
},
|
55
|
+
"ex:certainty": 0.9
|
56
|
+
}
|
57
|
+
|
58
|
+
Additionally, the `@annotation` property (or alias) may be used on a node object or value object to annotate the statement for which the associated node is the object of a triple.
|
59
|
+
|
60
|
+
{
|
61
|
+
"@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
|
62
|
+
"@id": "bob",
|
63
|
+
"foaf:age" 23,
|
64
|
+
"@annotation": {
|
65
|
+
"ex:certainty": 0.9
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
In the first case, the embedded node is not asserted, and only appears as the subject of a triple. In the second case, the triple is asserted and used as the subject in another statement which annotates it.
|
70
|
+
|
71
|
+
**Note: This feature is subject to change or elimination as the standards process progresses.**
|
72
|
+
|
73
|
+
#### Serializing a Graph containing embedded statements
|
74
|
+
|
75
|
+
require 'json-ld'
|
76
|
+
statement = RDF::Statement(RDF::URI('bob'), RDF::Vocab::FOAF.age, RDF::Literal(23))
|
77
|
+
graph = RDF::Graph.new << [statement, RDF::URI("ex:certainty"), RDF::Literal(0.9)]
|
78
|
+
graph.dump(:jsonld, validate: false, standard_prefixes: true)
|
79
|
+
# => {"@id": {"@id": "bob", "foaf:age" 23}, "ex:certainty": 0.9}
|
80
|
+
|
81
|
+
Alternatively, using the {JSON::LD::API.fromRdf} method:
|
82
|
+
|
83
|
+
JSON::LD::API::fromRdf(graph)
|
84
|
+
# => {"@id": {"@id": "bob", "foaf:age" 23}, "ex:certainty": 0.9}
|
85
|
+
|
86
|
+
#### Reading a Graph containing embedded statements
|
87
|
+
|
88
|
+
By default, {JSON::LD::API.toRdf} (and {JSON::LD::Reader}) will reject a document containing a subject resource.
|
89
|
+
|
90
|
+
jsonld = %({
|
91
|
+
"@id": {
|
92
|
+
"@id": "bob", "foaf:age" 23
|
93
|
+
},
|
94
|
+
"ex:certainty": 0.9
|
95
|
+
})
|
96
|
+
graph = RDF::Graph.new << JSON::LD::API.toRdf(input)
|
97
|
+
# => JSON::LD::JsonLdError::InvalidIdValue
|
98
|
+
|
99
|
+
{JSON::LD::API.toRdf} (and {JSON::LD::Reader}) support a boolean valued `rdfstar` option; only one statement is asserted, although the reified statement is contained within the graph.
|
100
|
+
|
101
|
+
graph = RDF::Graph.new do |graph|
|
102
|
+
JSON::LD::Reader.new(jsonld, rdfstar: true) {|reader| graph << reader}
|
103
|
+
end
|
104
|
+
graph.count #=> 1
|
36
105
|
|
37
106
|
## Examples
|
107
|
+
|
38
108
|
```ruby
|
39
109
|
require 'rubygems'
|
40
110
|
require 'json/ld'
|
41
111
|
```
|
112
|
+
|
42
113
|
### Expand a Document
|
114
|
+
|
43
115
|
```ruby
|
44
116
|
input = JSON.parse %({
|
45
117
|
"@context": {
|
@@ -59,8 +131,9 @@ require 'json/ld'
|
|
59
131
|
"http://xmlns.com/foaf/0.1/avatar": [{"@value": "https://twitter.com/account/profile_image/manusporny"}]
|
60
132
|
}]
|
61
133
|
```
|
134
|
+
|
62
135
|
### Compact a Document
|
63
|
-
|
136
|
+
|
64
137
|
input = JSON.parse %([{
|
65
138
|
"http://xmlns.com/foaf/0.1/name": ["Manu Sporny"],
|
66
139
|
"http://xmlns.com/foaf/0.1/homepage": [{"@id": "https://manu.sporny.org/"}],
|
@@ -86,9 +159,9 @@ require 'json/ld'
|
|
86
159
|
"homepage": "https://manu.sporny.org/",
|
87
160
|
"name": "Manu Sporny"
|
88
161
|
}
|
89
|
-
|
162
|
+
|
90
163
|
### Frame a Document
|
91
|
-
|
164
|
+
|
92
165
|
input = JSON.parse %({
|
93
166
|
"@context": {
|
94
167
|
"Book": "http://example.org/vocab#Book",
|
@@ -169,9 +242,9 @@ require 'json/ld'
|
|
169
242
|
}
|
170
243
|
]
|
171
244
|
}
|
172
|
-
|
245
|
+
|
173
246
|
### Turn JSON-LD into RDF (Turtle)
|
174
|
-
|
247
|
+
|
175
248
|
input = JSON.parse %({
|
176
249
|
"@context": {
|
177
250
|
"": "https://manu.sporny.org/",
|
@@ -192,9 +265,9 @@ require 'json/ld'
|
|
192
265
|
<http://example.org/people#joebob> a foaf:Person;
|
193
266
|
foaf:name "Joe Bob";
|
194
267
|
foaf:nick ("joe" "bob" "jaybe") .
|
195
|
-
|
268
|
+
|
196
269
|
### Turn RDF into JSON-LD
|
197
|
-
|
270
|
+
|
198
271
|
require 'rdf/turtle'
|
199
272
|
input = RDF::Graph.new << RDF::Turtle::Reader.new(%(
|
200
273
|
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
|
@@ -230,11 +303,12 @@ require 'json/ld'
|
|
230
303
|
"http://xmlns.com/foaf/0.1/name": [{"@value": "Manu Sporny"}]
|
231
304
|
}
|
232
305
|
]
|
233
|
-
|
306
|
+
|
234
307
|
## Use a custom Document Loader
|
235
308
|
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
309
|
|
237
310
|
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:
|
311
|
+
|
238
312
|
```ruby
|
239
313
|
load_document_local = Proc.new do |url, **options, &block|
|
240
314
|
if RDF::URI(url, canonicalize: true) == RDF::URI('http://schema.org/')
|
@@ -244,28 +318,34 @@ load_document_local = Proc.new do |url, **options, &block|
|
|
244
318
|
JSON::LD::API.documentLoader(url, options, &block)
|
245
319
|
end
|
246
320
|
end
|
321
|
+
|
247
322
|
```
|
248
323
|
Then, when performing something like expansion:
|
324
|
+
|
249
325
|
```ruby
|
250
326
|
JSON::LD::API.expand(input, documentLoader: load_document_local)
|
251
327
|
```
|
252
328
|
|
253
329
|
## Preloading contexts
|
254
330
|
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.
|
331
|
+
|
255
332
|
```ruby
|
256
333
|
ctx = JSON::LD::Context.new().parse('http://schema.org/')
|
257
334
|
JSON::LD::Context.add_preloaded('http://schema.org/', ctx)
|
258
335
|
```
|
336
|
+
|
259
337
|
On lookup, URIs with an `https` prefix are normalized to `http`.
|
260
338
|
|
261
339
|
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
340
|
|
263
341
|
## RDF Reader and Writer
|
264
342
|
{JSON::LD} also acts as a normal RDF reader and writer, using the standard RDF.rb reader/writer interfaces:
|
343
|
+
|
265
344
|
```ruby
|
266
345
|
graph = RDF::Graph.load("etc/doap.jsonld", format: :jsonld)
|
267
346
|
graph.dump(:jsonld, standard_prefixes: true)
|
268
347
|
```
|
348
|
+
|
269
349
|
`RDF::GRAPH#dump` can also take a `:context` option to use a separately defined context
|
270
350
|
|
271
351
|
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 +355,7 @@ This implementation is being used as a test-bed for features planned for an upco
|
|
275
355
|
|
276
356
|
### Scoped Contexts
|
277
357
|
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
|
-
|
358
|
+
|
279
359
|
{
|
280
360
|
"@context": {
|
281
361
|
"ex": "http://example.com/",
|
@@ -290,10 +370,10 @@ A term definition can include `@context`, which is applied to values of that obj
|
|
290
370
|
},
|
291
371
|
"foo": "Bar"
|
292
372
|
}
|
293
|
-
|
373
|
+
|
294
374
|
### @id and @type maps
|
295
375
|
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
|
-
|
376
|
+
|
297
377
|
{
|
298
378
|
"@context": {
|
299
379
|
"@vocab": "http://example/",
|
@@ -304,10 +384,10 @@ The value of `@container` in a term definition can include `@id` or `@type`, in
|
|
304
384
|
"_:bar": {"label": "Object with @id _:bar"}
|
305
385
|
}
|
306
386
|
}
|
307
|
-
|
387
|
+
|
308
388
|
### @graph containers and maps
|
309
389
|
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
|
-
|
390
|
+
|
311
391
|
{
|
312
392
|
"@context": {
|
313
393
|
"@vocab": "http://example.org/",
|
@@ -317,9 +397,9 @@ A term can have `@container` set to include `@graph` optionally including `@id`
|
|
317
397
|
"value": "x"
|
318
398
|
}
|
319
399
|
}
|
320
|
-
|
400
|
+
|
321
401
|
which expands to the following:
|
322
|
-
|
402
|
+
|
323
403
|
[{
|
324
404
|
"http://example.org/input": [{
|
325
405
|
"@graph": [{
|
@@ -327,18 +407,18 @@ which expands to the following:
|
|
327
407
|
}]
|
328
408
|
}]
|
329
409
|
}]
|
330
|
-
|
410
|
+
|
331
411
|
Compaction reverses this process, optionally ensuring that a single value is contained within an array of `@container` also includes `@set`:
|
332
|
-
|
412
|
+
|
333
413
|
{
|
334
414
|
"@context": {
|
335
415
|
"@vocab": "http://example.org/",
|
336
416
|
"input": {"@container": ["@graph", "@set"]}
|
337
417
|
}
|
338
418
|
}
|
339
|
-
|
419
|
+
|
340
420
|
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
|
-
|
421
|
+
|
342
422
|
{
|
343
423
|
"@context": {
|
344
424
|
"@vocab": "http://example.org/",
|
@@ -348,9 +428,9 @@ A graph map uses the map form already existing for `@index`, `@language`, `@type
|
|
348
428
|
"g1": {"value": "x"}
|
349
429
|
}
|
350
430
|
}
|
351
|
-
|
431
|
+
|
352
432
|
treats "g1" as an index, and expands to the following:
|
353
|
-
|
433
|
+
|
354
434
|
[{
|
355
435
|
"http://example.org/input": [{
|
356
436
|
"@index": "g1",
|
@@ -359,11 +439,11 @@ treats "g1" as an index, and expands to the following:
|
|
359
439
|
}]
|
360
440
|
}]
|
361
441
|
}])
|
362
|
-
|
442
|
+
|
363
443
|
This can also include `@set` to ensure that, when compacting, a single value of an index will be in array form.
|
364
444
|
|
365
445
|
The _id_ version is similar:
|
366
|
-
|
446
|
+
|
367
447
|
{
|
368
448
|
"@context": {
|
369
449
|
"@vocab": "http://example.org/",
|
@@ -373,9 +453,9 @@ The _id_ version is similar:
|
|
373
453
|
"http://example.com/g1": {"value": "x"}
|
374
454
|
}
|
375
455
|
}
|
376
|
-
|
456
|
+
|
377
457
|
which expands to:
|
378
|
-
|
458
|
+
|
379
459
|
[{
|
380
460
|
"http://example.org/input": [{
|
381
461
|
"@id": "http://example.com/g1",
|
@@ -384,10 +464,10 @@ which expands to:
|
|
384
464
|
}]
|
385
465
|
}]
|
386
466
|
}])
|
387
|
-
|
467
|
+
|
388
468
|
### Transparent Nesting
|
389
469
|
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
|
-
|
470
|
+
|
391
471
|
{
|
392
472
|
"@context": {
|
393
473
|
"skos": "http://www.w3.org/2004/02/skos/core#",
|
@@ -403,9 +483,9 @@ Many JSON APIs separate properties from their entities using an intermediate obj
|
|
403
483
|
"other_label": "This is the other label"
|
404
484
|
}
|
405
485
|
}
|
406
|
-
|
486
|
+
|
407
487
|
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
|
-
|
488
|
+
|
409
489
|
{
|
410
490
|
"@context": {
|
411
491
|
"skos": "http://www.w3.org/2004/02/skos/core#",
|
@@ -419,9 +499,9 @@ Many JSON APIs separate properties from their entities using an intermediate obj
|
|
419
499
|
"main_label": "This is the main label for my resource",
|
420
500
|
"other_label": "This is the other label"
|
421
501
|
}
|
422
|
-
|
502
|
+
|
423
503
|
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
|
-
|
504
|
+
|
425
505
|
{
|
426
506
|
"@context": {
|
427
507
|
"skos": "http://www.w3.org/2004/02/skos/core#",
|
@@ -437,7 +517,7 @@ Many JSON APIs separate properties from their entities using an intermediate obj
|
|
437
517
|
"other_label": "This is the other label"
|
438
518
|
}
|
439
519
|
}
|
440
|
-
|
520
|
+
|
441
521
|
In this way, nesting survives round-tripping through expansion, and framed output can include nested properties.
|
442
522
|
|
443
523
|
## Sinatra/Rack support
|
@@ -515,14 +595,14 @@ Note, the API method signatures differed in versions before 1.0, in that they al
|
|
515
595
|
## Installation
|
516
596
|
The recommended installation method is via [RubyGems](https://rubygems.org/).
|
517
597
|
To install the latest official release of the `JSON-LD` gem, do:
|
518
|
-
|
519
|
-
|
520
|
-
|
598
|
+
|
599
|
+
% [sudo] gem install json-ld
|
600
|
+
|
521
601
|
## Download
|
522
602
|
To get a local working copy of the development repository, do:
|
523
|
-
|
524
|
-
|
525
|
-
|
603
|
+
|
604
|
+
% git clone git://github.com/ruby-rdf/json-ld.git
|
605
|
+
|
526
606
|
## Mailing List
|
527
607
|
* <https://lists.w3.org/Archives/Public/public-rdf-ruby/>
|
528
608
|
|
@@ -540,7 +620,9 @@ To get a local working copy of the development repository, do:
|
|
540
620
|
list in the the `README`. Alphabetical order applies.
|
541
621
|
* Do note that in order for us to merge any non-trivial changes (as a rule
|
542
622
|
of thumb, additions larger than about 15 lines of code), we need an
|
543
|
-
explicit [public domain dedication][PDD] on record from you
|
623
|
+
explicit [public domain dedication][PDD] on record from you,
|
624
|
+
which you will be asked to agree to on the first commit to a repo within the organization.
|
625
|
+
Note that the agreement applies to all repos in the [Ruby RDF](https://github.com/ruby-rdf/) organization.
|
544
626
|
|
545
627
|
License
|
546
628
|
-------
|
@@ -552,8 +634,9 @@ see <https://unlicense.org/> or the accompanying {file:UNLICENSE} file.
|
|
552
634
|
[RDF]: https://www.w3.org/RDF/
|
553
635
|
[YARD]: https://yardoc.org/
|
554
636
|
[YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md
|
555
|
-
[PDD]: https://
|
637
|
+
[PDD]: https://unlicense.org/#unlicensing-contributions
|
556
638
|
[RDF.rb]: https://rubygems.org/gems/rdf
|
639
|
+
[JSON-LD-star]: https://json-ld.github.io/json-ld-star/
|
557
640
|
[Rack::LinkedData]: https://rubygems.org/gems/rack-linkeddata
|
558
641
|
[Backports]: https://rubygems.org/gems/backports
|
559
642
|
[JSON-LD]: https://www.w3.org/TR/json-ld11/ "JSON-LD 1.1"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.1.
|
1
|
+
3.1.9
|
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,41 +19,41 @@ 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,
|
22
|
+
reader_class.new(input, parser_options)
|
23
23
|
end
|
24
24
|
|
25
25
|
start = Time.new
|
26
26
|
if options[:expand]
|
27
|
-
|
27
|
+
parser_options = parser_options.merge(expandContext: parser_options.delete(:context)) if parser_options.key?(:context)
|
28
28
|
input = JSON::LD::API.fromRdf(reader) if reader
|
29
|
-
output = JSON::LD::API.expand(input,
|
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,
|
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,
|
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,
|
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
|
-
|
53
|
-
parser_options
|
54
|
-
reader ||= JSON::LD::Reader.new(input, parser_options)
|
52
|
+
parser_options = parser_options.merge(expandContext: parser_options.delete(:context)) if parser_options.key?(:context)
|
53
|
+
parser_options[:standard_prefixes] = true
|
54
|
+
reader ||= JSON::LD::Reader.new(input, **parser_options)
|
55
55
|
num = 0
|
56
|
-
RDF::Writer.for(options[:output_format]).new(options[:output], parser_options) do |w|
|
56
|
+
RDF::Writer.for(options[:output_format]).new(options[:output], **parser_options) do |w|
|
57
57
|
reader.each do |statement|
|
58
58
|
num += 1
|
59
59
|
w << statement
|
@@ -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,
|
@@ -114,6 +113,7 @@ OPT_ARGS = [
|
|
114
113
|
["--processingMode",GetoptLong::REQUIRED_ARGUMENT,"Set processing mode, defaults to json-ld-1.1"],
|
115
114
|
["--quiet", GetoptLong::NO_ARGUMENT, "Supress most output other than progress indicators"],
|
116
115
|
["--rename_bnodes", GetoptLong::OPTIONAL_ARGUMENT,"Rename bnodes as part of expansion, or keep them the same"],
|
116
|
+
["--rdfstar", GetoptLong::NO_ARGUMENT, "Parse JSON-LD-star"],
|
117
117
|
["--requireAll", GetoptLong::OPTIONAL_ARGUMENT,"Rename bnodes as part of expansion, or keep them the same"],
|
118
118
|
["--stream", GetoptLong::NO_ARGUMENT, "Use Streaming reader/writer"],
|
119
119
|
["--unique_bnodes", GetoptLong::OPTIONAL_ARGUMENT,"Use unique bnode identifiers"],
|
@@ -142,49 +142,48 @@ opts.each do |opt, arg|
|
|
142
142
|
case opt
|
143
143
|
when '--debug' then logger.level = Logger::DEBUG
|
144
144
|
when '--compact' then options[:compact] = true
|
145
|
-
when "--compactArrays" then
|
146
|
-
when '--context' then
|
145
|
+
when "--compactArrays" then parser_options[:compactArrays] = (arg || 'true') == 'true'
|
146
|
+
when '--context' then parser_options[:context] = RDF::URI(arg).absolute? ? arg : File.open(arg)
|
147
147
|
when '--evaluate' then input = arg
|
148
148
|
when '--expand' then options[:expand] = true
|
149
|
-
when "--expanded" then
|
150
|
-
when "--explicit" then
|
149
|
+
when "--expanded" then parser_options[:expanded] = (arg || 'true') == 'true'
|
150
|
+
when "--explicit" then parser_options[:compactArrays] = (arg || 'true') == 'true'
|
151
151
|
when '--format' then options[:output_format] = arg.to_sym
|
152
152
|
when '--flatten' then options[:flatten] = arg
|
153
|
-
when '--frame' then options[:frame] = arg
|
153
|
+
when '--frame' then options[:frame] = parser_otpions[:frame] = RDF::URI(arg).absolute? ? arg : File.open(arg)
|
154
154
|
when '--input-format' then options[:input_format] = arg.to_sym
|
155
|
-
when "--omitDefault" then
|
155
|
+
when "--omitDefault" then parser_options[:omitDefault] = (arg || 'true') == 'true'
|
156
156
|
when '--output' then options[:output] = File.open(arg, "w")
|
157
157
|
when '--parse-only' then options[:parse_only] = true
|
158
|
-
when '--processingMode' then
|
158
|
+
when '--processingMode' then parser_options[:processingMode] = arg
|
159
159
|
when '--quiet'
|
160
160
|
options[:quiet] = true
|
161
161
|
logger.level = Logger::FATAL
|
162
|
-
when "--
|
163
|
-
when "--
|
162
|
+
when "--rdfstar" then parser_options[:rdfstar] = true
|
163
|
+
when "--rename_bnodes" then parser_options[:rename_bnodes] = (arg || 'true') == 'true'
|
164
|
+
when "--requireAll" then parser_options[:requireAll] = (arg || 'true') == 'true'
|
164
165
|
when '--stream' then parser_options[:stream] = true
|
165
|
-
when "--unique_bnodes" then
|
166
|
+
when "--unique_bnodes" then parser_options[:unique_bnodes] = (arg || 'true') == 'true'
|
166
167
|
when '--uri' then parser_options[:base] = arg
|
167
168
|
when '--validate' then parser_options[:validate] = true
|
168
169
|
when '--help' then usage
|
169
170
|
when '--embed'
|
170
171
|
case arg
|
171
|
-
when '@always', '@never', '@link', '@
|
172
|
-
|
172
|
+
when '@always', '@never', '@link', '@once'
|
173
|
+
parser_options[:embed] = arg
|
173
174
|
when 'true'
|
174
|
-
|
175
|
+
parser_options[:embed] = '@never'
|
175
176
|
when 'false'
|
176
|
-
|
177
|
+
parser_options[:embed] = '@first'
|
177
178
|
else
|
178
|
-
STDERR.puts "--embed option takes one of @always, @never, @link,
|
179
|
+
STDERR.puts "--embed option takes one of @always, @never, @link, or @once"
|
179
180
|
exit(1)
|
180
181
|
end
|
181
182
|
end
|
182
183
|
end
|
183
184
|
|
184
185
|
# Hack
|
185
|
-
options
|
186
|
-
|
187
|
-
if !(options.keys & [:expand, :compact, :flatten, :frame]).empty? &&
|
186
|
+
if !(options.keys & %i{expand compact flatten frame}).empty? &&
|
188
187
|
(parser_options[:stream] || options[:output_format] != :jsonld)
|
189
188
|
STDERR.puts "Incompatible options"
|
190
189
|
exit(1)
|
@@ -192,11 +191,11 @@ end
|
|
192
191
|
|
193
192
|
if ARGV.empty?
|
194
193
|
s = input ? input : $stdin.read
|
195
|
-
run(StringIO.new(s), options)
|
194
|
+
run(StringIO.new(s), options, parser_options)
|
196
195
|
else
|
197
196
|
ARGV.each do |file|
|
198
197
|
# Call with opened files
|
199
|
-
RDF::Util::File.open_file(file, options) {|f| run(f, options)}
|
198
|
+
RDF::Util::File.open_file(file, **options) {|f| run(f, options, parser_options)}
|
200
199
|
end
|
201
200
|
end
|
202
201
|
puts
|