json-ld 3.2.4 → 3.3.0

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.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -4
  3. data/VERSION +1 -1
  4. data/lib/json/ld/api.rb +807 -771
  5. data/lib/json/ld/compact.rb +304 -304
  6. data/lib/json/ld/conneg.rb +179 -161
  7. data/lib/json/ld/context.rb +2079 -1913
  8. data/lib/json/ld/expand.rb +745 -666
  9. data/lib/json/ld/extensions.rb +14 -13
  10. data/lib/json/ld/flatten.rb +257 -247
  11. data/lib/json/ld/format.rb +202 -194
  12. data/lib/json/ld/frame.rb +525 -502
  13. data/lib/json/ld/from_rdf.rb +223 -204
  14. data/lib/json/ld/html/nokogiri.rb +123 -121
  15. data/lib/json/ld/html/rexml.rb +151 -147
  16. data/lib/json/ld/reader.rb +107 -100
  17. data/lib/json/ld/resource.rb +224 -205
  18. data/lib/json/ld/streaming_reader.rb +574 -507
  19. data/lib/json/ld/streaming_writer.rb +93 -92
  20. data/lib/json/ld/to_rdf.rb +171 -169
  21. data/lib/json/ld/utils.rb +270 -264
  22. data/lib/json/ld/version.rb +24 -14
  23. data/lib/json/ld/writer.rb +334 -311
  24. data/lib/json/ld.rb +103 -96
  25. metadata +56 -225
  26. data/spec/api_spec.rb +0 -132
  27. data/spec/compact_spec.rb +0 -3482
  28. data/spec/conneg_spec.rb +0 -373
  29. data/spec/context_spec.rb +0 -2056
  30. data/spec/expand_spec.rb +0 -4496
  31. data/spec/flatten_spec.rb +0 -1203
  32. data/spec/format_spec.rb +0 -115
  33. data/spec/frame_spec.rb +0 -2541
  34. data/spec/from_rdf_spec.rb +0 -1072
  35. data/spec/matchers.rb +0 -20
  36. data/spec/rdfstar_spec.rb +0 -25
  37. data/spec/reader_spec.rb +0 -883
  38. data/spec/resource_spec.rb +0 -76
  39. data/spec/spec_helper.rb +0 -281
  40. data/spec/streaming_reader_spec.rb +0 -237
  41. data/spec/streaming_writer_spec.rb +0 -145
  42. data/spec/suite_compact_spec.rb +0 -22
  43. data/spec/suite_expand_spec.rb +0 -36
  44. data/spec/suite_flatten_spec.rb +0 -34
  45. data/spec/suite_frame_spec.rb +0 -29
  46. data/spec/suite_from_rdf_spec.rb +0 -22
  47. data/spec/suite_helper.rb +0 -411
  48. data/spec/suite_html_spec.rb +0 -22
  49. data/spec/suite_http_spec.rb +0 -35
  50. data/spec/suite_remote_doc_spec.rb +0 -22
  51. data/spec/suite_to_rdf_spec.rb +0 -30
  52. data/spec/support/extensions.rb +0 -44
  53. data/spec/test-files/test-1-compacted.jsonld +0 -10
  54. data/spec/test-files/test-1-context.jsonld +0 -7
  55. data/spec/test-files/test-1-expanded.jsonld +0 -5
  56. data/spec/test-files/test-1-input.jsonld +0 -10
  57. data/spec/test-files/test-1-rdf.ttl +0 -8
  58. data/spec/test-files/test-2-compacted.jsonld +0 -20
  59. data/spec/test-files/test-2-context.jsonld +0 -7
  60. data/spec/test-files/test-2-expanded.jsonld +0 -16
  61. data/spec/test-files/test-2-input.jsonld +0 -20
  62. data/spec/test-files/test-2-rdf.ttl +0 -14
  63. data/spec/test-files/test-3-compacted.jsonld +0 -11
  64. data/spec/test-files/test-3-context.jsonld +0 -8
  65. data/spec/test-files/test-3-expanded.jsonld +0 -10
  66. data/spec/test-files/test-3-input.jsonld +0 -11
  67. data/spec/test-files/test-3-rdf.ttl +0 -8
  68. data/spec/test-files/test-4-compacted.jsonld +0 -10
  69. data/spec/test-files/test-4-context.jsonld +0 -7
  70. data/spec/test-files/test-4-expanded.jsonld +0 -6
  71. data/spec/test-files/test-4-input.jsonld +0 -10
  72. data/spec/test-files/test-4-rdf.ttl +0 -5
  73. data/spec/test-files/test-5-compacted.jsonld +0 -13
  74. data/spec/test-files/test-5-context.jsonld +0 -7
  75. data/spec/test-files/test-5-expanded.jsonld +0 -9
  76. data/spec/test-files/test-5-input.jsonld +0 -13
  77. data/spec/test-files/test-5-rdf.ttl +0 -7
  78. data/spec/test-files/test-6-compacted.jsonld +0 -10
  79. data/spec/test-files/test-6-context.jsonld +0 -7
  80. data/spec/test-files/test-6-expanded.jsonld +0 -10
  81. data/spec/test-files/test-6-input.jsonld +0 -10
  82. data/spec/test-files/test-6-rdf.ttl +0 -6
  83. data/spec/test-files/test-7-compacted.jsonld +0 -23
  84. data/spec/test-files/test-7-context.jsonld +0 -4
  85. data/spec/test-files/test-7-expanded.jsonld +0 -20
  86. data/spec/test-files/test-7-input.jsonld +0 -23
  87. data/spec/test-files/test-7-rdf.ttl +0 -14
  88. data/spec/test-files/test-8-compacted.jsonld +0 -34
  89. data/spec/test-files/test-8-context.jsonld +0 -11
  90. data/spec/test-files/test-8-expanded.jsonld +0 -24
  91. data/spec/test-files/test-8-frame.jsonld +0 -18
  92. data/spec/test-files/test-8-framed.jsonld +0 -25
  93. data/spec/test-files/test-8-input.jsonld +0 -30
  94. data/spec/test-files/test-8-rdf.ttl +0 -15
  95. data/spec/test-files/test-9-compacted.jsonld +0 -20
  96. data/spec/test-files/test-9-context.jsonld +0 -13
  97. data/spec/test-files/test-9-expanded.jsonld +0 -14
  98. data/spec/test-files/test-9-input.jsonld +0 -12
  99. data/spec/to_rdf_spec.rb +0 -1684
  100. data/spec/writer_spec.rb +0 -427
data/spec/to_rdf_spec.rb DELETED
@@ -1,1684 +0,0 @@
1
- # coding: utf-8
2
- require_relative 'spec_helper'
3
-
4
- describe JSON::LD::API do
5
- let(:logger) {RDF::Spec.logger}
6
-
7
- context ".toRdf" do
8
- it "should implement RDF::Enumerable" do
9
- expect(JSON::LD::API.toRdf({})).to be_a(RDF::Enumerable)
10
- end
11
-
12
- context "unnamed nodes" do
13
- {
14
- "no @id" => [
15
- %q({
16
- "http://example.com/foo": "bar"
17
- }),
18
- %q([ <http://example.com/foo> "bar"^^xsd:string] .)
19
- ],
20
- "@id with _:a" => [
21
- %q({
22
- "@id": "_:a",
23
- "http://example.com/foo": "bar"
24
- }),
25
- %q([ <http://example.com/foo> "bar"^^xsd:string] .)
26
- ],
27
- "@id with _:a and reference" => [
28
- %q({
29
- "@id": "_:a",
30
- "http://example.com/foo": {"@id": "_:a"}
31
- }),
32
- %q(_:a <http://example.com/foo> _:a .)
33
- ],
34
- }.each do |title, (js, ttl)|
35
- it title do
36
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
37
- expect(parse(js)).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
38
- end
39
- end
40
- end
41
-
42
- context "nodes with @id" do
43
- {
44
- "with IRI" => [
45
- %q({
46
- "@id": "http://example.com/a",
47
- "http://example.com/foo": "bar"
48
- }),
49
- %q(<http://example.com/a> <http://example.com/foo> "bar" .)
50
- ],
51
- }.each do |title, (js, ttl)|
52
- it title do
53
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
54
- expect(parse(js)).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
55
- end
56
- end
57
-
58
- context "with relative IRIs" do
59
- {
60
- "base" => [
61
- %({
62
- "@id": "",
63
- "@type": "#{RDF::RDFS.Resource}"
64
- }),
65
- %(<http://example.org/> a <#{RDF::RDFS.Resource}> .)
66
- ],
67
- "relative" => [
68
- %({
69
- "@id": "a/b",
70
- "@type": "#{RDF::RDFS.Resource}"
71
- }),
72
- %(<http://example.org/a/b> a <#{RDF::RDFS.Resource}> .)
73
- ],
74
- "hash" => [
75
- %({
76
- "@id": "#a",
77
- "@type": "#{RDF::RDFS.Resource}"
78
- }),
79
- %(<http://example.org/#a> a <#{RDF::RDFS.Resource}> .)
80
- ],
81
- }.each do |title, (js, ttl)|
82
- it title do
83
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
84
- expect(parse(js, base: "http://example.org/")).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
85
- end
86
- end
87
- end
88
- end
89
-
90
- context "typed nodes" do
91
- {
92
- "one type" => [
93
- %q({
94
- "@type": "http://example.com/foo"
95
- }),
96
- %q([ a <http://example.com/foo> ] .)
97
- ],
98
- "two types" => [
99
- %q({
100
- "@type": ["http://example.com/foo", "http://example.com/baz"]
101
- }),
102
- %q([ a <http://example.com/foo>, <http://example.com/baz> ] .)
103
- ],
104
- "blank node type" => [
105
- %q({
106
- "@type": "_:foo"
107
- }),
108
- %q([ a _:foo ] .)
109
- ]
110
- }.each do |title, (js, ttl)|
111
- it title do
112
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
113
- expect(parse(js)).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
114
- end
115
- end
116
- end
117
-
118
- context "key/value" do
119
- {
120
- "string" => [
121
- %q({
122
- "http://example.com/foo": "bar"
123
- }),
124
- %q([ <http://example.com/foo> "bar"^^xsd:string ] .)
125
- ],
126
- "strings" => [
127
- %q({
128
- "http://example.com/foo": ["bar", "baz"]
129
- }),
130
- %q([ <http://example.com/foo> "bar"^^xsd:string, "baz"^^xsd:string ] .)
131
- ],
132
- "IRI" => [
133
- %q({
134
- "http://example.com/foo": {"@id": "http://example.com/bar"}
135
- }),
136
- %q([ <http://example.com/foo> <http://example.com/bar> ] .)
137
- ],
138
- "IRIs" => [
139
- %q({
140
- "http://example.com/foo": [{"@id": "http://example.com/bar"}, {"@id": "http://example.com/baz"}]
141
- }),
142
- %q([ <http://example.com/foo> <http://example.com/bar>, <http://example.com/baz> ] .)
143
- ],
144
- }.each do |title, (js, ttl)|
145
- it title do
146
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
147
- expect(parse(js)).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
148
- end
149
- end
150
- end
151
-
152
- context "literals" do
153
- {
154
- "plain literal" =>
155
- [
156
- %q({"@id": "http://greggkellogg.net/foaf#me", "http://xmlns.com/foaf/0.1/name": "Gregg Kellogg"}),
157
- %q(<http://greggkellogg.net/foaf#me> <http://xmlns.com/foaf/0.1/name> "Gregg Kellogg" .)
158
- ],
159
- "explicit plain literal" =>
160
- [
161
- %q({"http://xmlns.com/foaf/0.1/name": {"@value": "Gregg Kellogg"}}),
162
- %q(_:a <http://xmlns.com/foaf/0.1/name> "Gregg Kellogg"^^xsd:string .)
163
- ],
164
- "language tagged literal" =>
165
- [
166
- %q({"http://www.w3.org/2000/01/rdf-schema#label": {"@value": "A plain literal with a lang tag.", "@language": "en-us"}}),
167
- %q(_:a <http://www.w3.org/2000/01/rdf-schema#label> "A plain literal with a lang tag."@en-us .)
168
- ],
169
- "I18N literal with language" =>
170
- [
171
- %q([{
172
- "@id": "http://greggkellogg.net/foaf#me",
173
- "http://xmlns.com/foaf/0.1/knows": {"@id": "http://www.ivan-herman.net/foaf#me"}
174
- },{
175
- "@id": "http://www.ivan-herman.net/foaf#me",
176
- "http://xmlns.com/foaf/0.1/name": {"@value": "Herman Iván", "@language": "hu"}
177
- }]),
178
- %q(
179
- <http://greggkellogg.net/foaf#me> <http://xmlns.com/foaf/0.1/knows> <http://www.ivan-herman.net/foaf#me> .
180
- <http://www.ivan-herman.net/foaf#me> <http://xmlns.com/foaf/0.1/name> "Herman Iv\u00E1n"@hu .
181
- )
182
- ],
183
- "explicit datatyped literal" =>
184
- [
185
- %q({
186
- "@id": "http://greggkellogg.net/foaf#me",
187
- "http://purl.org/dc/terms/created": {"@value": "1957-02-27", "@type": "http://www.w3.org/2001/XMLSchema#date"}
188
- }),
189
- %q(
190
- <http://greggkellogg.net/foaf#me> <http://purl.org/dc/terms/created> "1957-02-27"^^<http://www.w3.org/2001/XMLSchema#date> .
191
- )
192
- ],
193
- }.each do |title, (js, ttl)|
194
- it title do
195
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
196
- expect(parse(js)).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
197
- end
198
- end
199
-
200
- context "with @type: @json" do
201
- {
202
- "true": {
203
- input: %({
204
- "@context": {
205
- "@version": 1.1,
206
- "e": {"@id": "http://example.org/vocab#bool", "@type": "@json"}
207
- },
208
- "e": true
209
- }),
210
- output:%(
211
- @prefix ex: <http://example.org/vocab#> .
212
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
213
- [ex:bool "true"^^rdf:JSON] .
214
- )
215
- },
216
- "false": {
217
- input: %({
218
- "@context": {
219
- "@version": 1.1,
220
- "e": {"@id": "http://example.org/vocab#bool", "@type": "@json"}
221
- },
222
- "e": false
223
- }),
224
- output: %(
225
- @prefix ex: <http://example.org/vocab#> .
226
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
227
- [ex:bool "false"^^rdf:JSON] .
228
- )
229
- },
230
- "double": {
231
- input: %({
232
- "@context": {
233
- "@version": 1.1,
234
- "e": {"@id": "http://example.org/vocab#double", "@type": "@json"}
235
- },
236
- "e": 1.23
237
- }),
238
- output: %(
239
- @prefix ex: <http://example.org/vocab#> .
240
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
241
- [ex:double "1.23"^^rdf:JSON] .
242
- )
243
- },
244
- "double-zero": {
245
- input: %({
246
- "@context": {
247
- "@version": 1.1,
248
- "e": {"@id": "http://example.org/vocab#double", "@type": "@json"}
249
- },
250
- "e": 0
251
- }),
252
- output: %(
253
- @prefix ex: <http://example.org/vocab#> .
254
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
255
- [ex:double "0"^^rdf:JSON] .
256
- )
257
- },
258
- "integer": {
259
- input: %({
260
- "@context": {
261
- "@version": 1.1,
262
- "e": {"@id": "http://example.org/vocab#integer", "@type": "@json"}
263
- },
264
- "e": 123
265
- }),
266
- output: %(
267
- @prefix ex: <http://example.org/vocab#> .
268
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
269
- [ex:integer "123"^^rdf:JSON] .
270
- )
271
- },
272
- "string": {
273
- input: %({
274
- "@context": {
275
- "@version": 1.1,
276
- "e": {"@id": "http://example.org/vocab#string", "@type": "@json"}
277
- },
278
- "e": "string"
279
- }),
280
- output: %(
281
- @prefix ex: <http://example.org/vocab#> .
282
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
283
- [ex:string "\\"string\\""^^rdf:JSON] .
284
- )
285
- },
286
- "null": {
287
- input: %({
288
- "@context": {
289
- "@version": 1.1,
290
- "e": {"@id": "http://example.org/vocab#null", "@type": "@json"}
291
- },
292
- "e": null
293
- }),
294
- output: %(
295
- @prefix ex: <http://example.org/vocab#> .
296
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
297
- [ex:null "null"^^rdf:JSON] .
298
- )
299
- },
300
- "object": {
301
- input: %({
302
- "@context": {
303
- "@version": 1.1,
304
- "e": {"@id": "http://example.org/vocab#object", "@type": "@json"}
305
- },
306
- "e": {"foo": "bar"}
307
- }),
308
- output: %(
309
- @prefix ex: <http://example.org/vocab#> .
310
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
311
- [ex:object """{"foo":"bar"}"""^^rdf:JSON] .
312
- )
313
- },
314
- "array": {
315
- input: %({
316
- "@context": {
317
- "@version": 1.1,
318
- "e": {"@id": "http://example.org/vocab#array", "@type": "@json"}
319
- },
320
- "e": [{"foo": "bar"}]
321
- }),
322
- output: %(
323
- @prefix ex: <http://example.org/vocab#> .
324
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
325
- [ex:array """[{"foo":"bar"}]"""^^rdf:JSON] .
326
- )
327
- },
328
- "c14n-arrays": {
329
- input: %({
330
- "@context": {
331
- "@version": 1.1,
332
- "e": {"@id": "http://example.org/vocab#c14n", "@type": "@json"}
333
- },
334
- "e": [
335
- 56,
336
- {
337
- "d": true,
338
- "10": null,
339
- "1": [ ]
340
- }
341
- ]
342
- }),
343
- output: %(
344
- @prefix ex: <http://example.org/vocab#> .
345
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
346
- [ex:c14n """[56,{"1":[],"10":null,"d":true}]"""^^rdf:JSON] .
347
- )
348
- },
349
- "c14n-french": {
350
- input: %({
351
- "@context": {
352
- "@version": 1.1,
353
- "e": {"@id": "http://example.org/vocab#c14n", "@type": "@json"}
354
- },
355
- "e": {
356
- "peach": "This sorting order",
357
- "péché": "is wrong according to French",
358
- "pêche": "but canonicalization MUST",
359
- "sin": "ignore locale"
360
- }
361
- }),
362
- output: %(
363
- @prefix ex: <http://example.org/vocab#> .
364
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
365
- [ex:c14n """{"peach":"This sorting order","péché":"is wrong according to French","pêche":"but canonicalization MUST","sin":"ignore locale"}"""^^rdf:JSON] .
366
- )
367
- },
368
- "c14n-structures": {
369
- input: %({
370
- "@context": {
371
- "@version": 1.1,
372
- "e": {"@id": "http://example.org/vocab#c14n", "@type": "@json"}
373
- },
374
- "e": {
375
- "1": {"f": {"f": "hi","F": 5} ," ": 56.0},
376
- "10": { },
377
- "": "empty",
378
- "a": { },
379
- "111": [ {"e": "yes","E": "no" } ],
380
- "A": { }
381
- }
382
- }),
383
- output: %(
384
- @prefix ex: <http://example.org/vocab#> .
385
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
386
- [ex:c14n """{"":"empty","1":{" ":56,"f":{"F":5,"f":"hi"}},"10":{},"111":[{"E":"no","e":"yes"}],"A":{},"a":{}}"""^^rdf:JSON] .
387
- )
388
- },
389
- "c14n-unicode": {
390
- input: %({
391
- "@context": {
392
- "@version": 1.1,
393
- "e": {"@id": "http://example.org/vocab#c14n", "@type": "@json"}
394
- },
395
- "e": {
396
- "Unnormalized Unicode":"A\u030a"
397
- }
398
- }),
399
- output: %(
400
- @prefix ex: <http://example.org/vocab#> .
401
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
402
- [ex:c14n """{"Unnormalized Unicode":"Å"}"""^^rdf:JSON] .
403
- )
404
- },
405
- }.each do |title, params|
406
- it title do
407
- params[:output] = RDF::Graph.new << RDF::Turtle::Reader.new(params[:output])
408
- run_to_rdf params
409
- end
410
- end
411
- end
412
-
413
- context "with xsd: true" do
414
- {
415
- "true": {
416
- input: {
417
- "@context" => {
418
- "e" => "http://example.org/vocab#e"
419
- },
420
- "e" => RDF::Literal(true)
421
- },
422
- output: %(
423
- @prefix ex: <http://example.org/vocab#> .
424
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
425
- [ex:e true] .
426
- )
427
- },
428
- "integer": {
429
- input: {
430
- "@context" => {
431
- "e" => "http://example.org/vocab#e"
432
- },
433
- "e" => RDF::Literal(1)
434
- },
435
- output: %(
436
- @prefix ex: <http://example.org/vocab#> .
437
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
438
- [ex:e 1] .
439
- )
440
- },
441
- "decimal": {
442
- input: {
443
- "@context" => {
444
- "e" => "http://example.org/vocab#e"
445
- },
446
- "e" => RDF::Literal::Decimal.new("1.1")
447
- },
448
- output: %(
449
- @prefix ex: <http://example.org/vocab#> .
450
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
451
- [ex:e 1.1] .
452
- )
453
- },
454
- "float": {
455
- input: {
456
- "@context" => {
457
- "e" => "http://example.org/vocab#e"
458
- },
459
- "e" => RDF::Literal.new("1.1e1", datatype: RDF::XSD.float)
460
- },
461
- output: %(
462
- @prefix ex: <http://example.org/vocab#> .
463
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
464
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
465
- [ex:e "1.1e1"^^xsd:float] .
466
- )
467
- },
468
- "double": {
469
- input: {
470
- "@context" => {
471
- "e" => "http://example.org/vocab#e"
472
- },
473
- "e" => RDF::Literal.new("1.1e1", datatype: RDF::XSD.double)
474
- },
475
- output: %(
476
- @prefix ex: <http://example.org/vocab#> .
477
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
478
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
479
- [ex:e 1.1e1] .
480
- )
481
- },
482
- "date": {
483
- input: {
484
- "@context" => {
485
- "e" => "http://example.org/vocab#e"
486
- },
487
- "e" => RDF::Literal.new("2022-08-27", datatype: RDF::XSD.date)
488
- },
489
- output: %(
490
- @prefix ex: <http://example.org/vocab#> .
491
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
492
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
493
- [ex:e "2022-08-27"^^xsd:date] .
494
- )
495
- },
496
- "time": {
497
- input: {
498
- "@context" => {
499
- "e" => "http://example.org/vocab#e"
500
- },
501
- "e" => RDF::Literal.new("12:00:00", datatype: RDF::XSD.time)
502
- },
503
- output: %(
504
- @prefix ex: <http://example.org/vocab#> .
505
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
506
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
507
- [ex:e "12:00:00"^^xsd:time] .
508
- )
509
- },
510
- "dateTime": {
511
- input: {
512
- "@context" => {
513
- "e" => "http://example.org/vocab#e"
514
- },
515
- "e" => RDF::Literal.new("2022-08-27T12:00:00", datatype: RDF::XSD.dateTime)
516
- },
517
- output: %(
518
- @prefix ex: <http://example.org/vocab#> .
519
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
520
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
521
- [ex:e "2022-08-27T12:00:00"^^xsd:dateTime] .
522
- )
523
- },
524
- "language": {
525
- input: {
526
- "@context" => {
527
- "e" => "http://example.org/vocab#e"
528
- },
529
- "e" => RDF::Literal.new("language", language: :"en-us")
530
- },
531
- output: %(
532
- @prefix ex: <http://example.org/vocab#> .
533
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
534
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
535
- [ex:e "language"@en-us] .
536
- )
537
- },
538
- }.each do |title, params|
539
- it title do
540
- params[:output] = RDF::Graph.new << RDF::Turtle::Reader.new(params[:output])
541
- run_to_rdf(params.merge(xsd: true))
542
- end
543
- end
544
- end
545
- end
546
-
547
- context "prefixes" do
548
- {
549
- "empty suffix" => [
550
- %q({"@context": {"prefix": "http://example.com/default#"}, "prefix:": "bar"}),
551
- %q(_:a <http://example.com/default#> "bar"^^xsd:string .)
552
- ],
553
- "prefix:suffix" => [
554
- %q({"@context": {"prefix": "http://example.com/default#"}, "prefix:foo": "bar"}),
555
- %q(_:a <http://example.com/default#foo> "bar"^^xsd:string .)
556
- ]
557
- }.each_pair do |title, (js, ttl)|
558
- it title do
559
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
560
- expect(parse(js)).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
561
- end
562
- end
563
- end
564
-
565
- context "overriding keywords" do
566
- {
567
- "'url' for @id, 'a' for @type" => [
568
- %q({
569
- "@context": {"url": "@id", "a": "@type", "name": "http://schema.org/name"},
570
- "url": "http://example.com/about#gregg",
571
- "a": "http://schema.org/Person",
572
- "name": "Gregg Kellogg"
573
- }),
574
- %q(
575
- <http://example.com/about#gregg> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://schema.org/Person> .
576
- <http://example.com/about#gregg> <http://schema.org/name> "Gregg Kellogg"^^xsd:string .
577
- )
578
- ],
579
- }.each do |title, (js, ttl)|
580
- it title do
581
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
582
- expect(parse(js)).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
583
- end
584
- end
585
- end
586
-
587
- context "chaining" do
588
- {
589
- "explicit subject" =>
590
- [
591
- %q({
592
- "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
593
- "@id": "http://greggkellogg.net/foaf#me",
594
- "foaf:knows": {
595
- "@id": "http://www.ivan-herman.net/foaf#me",
596
- "foaf:name": "Ivan Herman"
597
- }
598
- }),
599
- %q(
600
- <http://greggkellogg.net/foaf#me> <http://xmlns.com/foaf/0.1/knows> <http://www.ivan-herman.net/foaf#me> .
601
- <http://www.ivan-herman.net/foaf#me> <http://xmlns.com/foaf/0.1/name> "Ivan Herman" .
602
- )
603
- ],
604
- "implicit subject" =>
605
- [
606
- %q({
607
- "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
608
- "@id": "http://greggkellogg.net/foaf#me",
609
- "foaf:knows": {
610
- "foaf:name": "Manu Sporny"
611
- }
612
- }),
613
- %q(
614
- <http://greggkellogg.net/foaf#me> <http://xmlns.com/foaf/0.1/knows> _:a .
615
- _:a <http://xmlns.com/foaf/0.1/name> "Manu Sporny"^^xsd:string .
616
- )
617
- ],
618
- }.each do |title, (js, ttl)|
619
- it title do
620
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
621
- expect(parse(js)).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
622
- end
623
- end
624
- end
625
-
626
- context "multiple values" do
627
- {
628
- "literals" =>
629
- [
630
- %q({
631
- "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
632
- "@id": "http://greggkellogg.net/foaf#me",
633
- "foaf:knows": ["Manu Sporny", "Ivan Herman"]
634
- }),
635
- %q(
636
- <http://greggkellogg.net/foaf#me> <http://xmlns.com/foaf/0.1/knows> "Manu Sporny" .
637
- <http://greggkellogg.net/foaf#me> <http://xmlns.com/foaf/0.1/knows> "Ivan Herman" .
638
- )
639
- ],
640
- }.each do |title, (js, ttl)|
641
- it title do
642
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
643
- expect(parse(js)).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
644
- end
645
- end
646
- end
647
-
648
- context "lists" do
649
- {
650
- "Empty" => [
651
- %q({
652
- "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
653
- "@id": "http://greggkellogg.net/foaf#me",
654
- "foaf:knows": {"@list": []}
655
- }),
656
- %q(
657
- <http://greggkellogg.net/foaf#me> <http://xmlns.com/foaf/0.1/knows> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> .
658
- )
659
- ],
660
- "single value" => [
661
- %q({
662
- "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
663
- "@id": "http://greggkellogg.net/foaf#me",
664
- "foaf:knows": {"@list": ["Manu Sporny"]}
665
- }),
666
- %q(
667
- <http://greggkellogg.net/foaf#me> <http://xmlns.com/foaf/0.1/knows> _:a .
668
- _:a <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "Manu Sporny"^^xsd:string .
669
- _:a <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> .
670
- )
671
- ],
672
- "single value (with coercion)" => [
673
- %q({
674
- "@context": {
675
- "foaf": "http://xmlns.com/foaf/0.1/",
676
- "foaf:knows": { "@container": "@list"}
677
- },
678
- "@id": "http://greggkellogg.net/foaf#me",
679
- "foaf:knows": ["Manu Sporny"]
680
- }),
681
- %q(
682
- <http://greggkellogg.net/foaf#me> <http://xmlns.com/foaf/0.1/knows> _:a .
683
- _:a <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "Manu Sporny"^^xsd:string .
684
- _:a <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> .
685
- )
686
- ],
687
- "multiple values" => [
688
- %q({
689
- "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
690
- "@id": "http://greggkellogg.net/foaf#me",
691
- "foaf:knows": {"@list": ["Manu Sporny", "Dave Longley"]}
692
- }),
693
- %q(
694
- <http://greggkellogg.net/foaf#me> <http://xmlns.com/foaf/0.1/knows> _:a .
695
- _:a <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "Manu Sporny"^^xsd:string .
696
- _:a <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b .
697
- _:b <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "Dave Longley"^^xsd:string .
698
- _:b <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> .
699
- )
700
- ],
701
- "@list containing @list" => [
702
- %q({
703
- "@id": "http://example/A",
704
- "http://example.com/foo": {"@list": [{"@list": ["baz"]}]}
705
- }),
706
- %q(
707
- <http://example/A> <http://example.com/foo> (("baz")) .
708
- )
709
- ],
710
- "@list containing empty @list" => [
711
- %({
712
- "@id": "http://example/A",
713
- "http://example.com/foo": {"@list": [{"@list": []}]}
714
- }),
715
- %q(
716
- <http://example/A> <http://example.com/foo> (()) .
717
- )
718
- ],
719
- }.each do |title, (js, ttl)|
720
- it title do
721
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
722
- expect(parse(js)).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
723
- end
724
- end
725
- end
726
-
727
- context "context" do
728
- {
729
- "@id coersion" =>
730
- [
731
- %q({
732
- "@context": {
733
- "knows": {"@id": "http://xmlns.com/foaf/0.1/knows", "@type": "@id"}
734
- },
735
- "@id": "http://greggkellogg.net/foaf#me",
736
- "knows": "http://www.ivan-herman.net/foaf#me"
737
- }),
738
- %q(
739
- <http://greggkellogg.net/foaf#me> <http://xmlns.com/foaf/0.1/knows> <http://www.ivan-herman.net/foaf#me> .
740
- )
741
- ],
742
- "datatype coersion" =>
743
- [
744
- %q({
745
- "@context": {
746
- "dcterms": "http://purl.org/dc/terms/",
747
- "xsd": "http://www.w3.org/2001/XMLSchema#",
748
- "created": {"@id": "http://purl.org/dc/terms/created", "@type": "xsd:date"}
749
- },
750
- "@id": "http://greggkellogg.net/foaf#me",
751
- "created": "1957-02-27"
752
- }),
753
- %q(
754
- <http://greggkellogg.net/foaf#me> <http://purl.org/dc/terms/created> "1957-02-27"^^<http://www.w3.org/2001/XMLSchema#date> .
755
- )
756
- ],
757
- "sub-objects with context" => [
758
- %q({
759
- "@context": {"foo": "http://example.com/foo"},
760
- "foo": {
761
- "@context": {"foo": "http://example.org/foo"},
762
- "foo": "bar"
763
- }
764
- }),
765
- %q(
766
- _:a <http://example.com/foo> _:b .
767
- _:b <http://example.org/foo> "bar"^^xsd:string .
768
- )
769
- ],
770
- "contexts with a list processed in order" => [
771
- %q({
772
- "@context": [
773
- {"foo": "http://example.com/foo"},
774
- {"foo": "http://example.org/foo"}
775
- ],
776
- "foo": "bar"
777
- }),
778
- %q(
779
- _:b <http://example.org/foo> "bar"^^xsd:string .
780
- )
781
- ],
782
- "term definition resolves term as IRI" => [
783
- %q({
784
- "@context": [
785
- {"foo": "http://example.com/foo"},
786
- {"bar": "foo"}
787
- ],
788
- "bar": "bar"
789
- }),
790
- %q(
791
- _:b <http://example.com/foo> "bar"^^xsd:string .
792
- )
793
- ],
794
- "term definition resolves prefix as IRI" => [
795
- %q({
796
- "@context": [
797
- {"foo": "http://example.com/foo#"},
798
- {"bar": "foo:bar"}
799
- ],
800
- "bar": "bar"
801
- }),
802
- %q(
803
- _:b <http://example.com/foo#bar> "bar"^^xsd:string .
804
- )
805
- ],
806
- "@language" => [
807
- %q({
808
- "@context": {
809
- "foo": "http://example.com/foo#",
810
- "@language": "en"
811
- },
812
- "foo:bar": "baz"
813
- }),
814
- %q(
815
- _:a <http://example.com/foo#bar> "baz"@en .
816
- )
817
- ],
818
- "@language with override" => [
819
- %q({
820
- "@context": {
821
- "foo": "http://example.com/foo#",
822
- "@language": "en"
823
- },
824
- "foo:bar": {"@value": "baz", "@language": "fr"}
825
- }),
826
- %q(
827
- _:a <http://example.com/foo#bar> "baz"@fr .
828
- )
829
- ],
830
- "@language with plain" => [
831
- %q({
832
- "@context": {
833
- "foo": "http://example.com/foo#",
834
- "@language": "en"
835
- },
836
- "foo:bar": {"@value": "baz"}
837
- }),
838
- %q(
839
- _:a <http://example.com/foo#bar> "baz"^^xsd:string .
840
- )
841
- ],
842
- }.each do |title, (js, ttl)|
843
- it title do
844
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
845
- expect(parse(js)).to be_equivalent_graph(ttl, base: "http://example/", logger: logger, inputDocument: js)
846
- end
847
- end
848
-
849
- context "coercion" do
850
- context "term def with @id + @type" do
851
- {
852
- "dt with term" => [
853
- %q({
854
- "@context": [
855
- {"date": "http://www.w3.org/2001/XMLSchema#date", "term": "http://example.org/foo#"},
856
- {"foo": {"@id": "term", "@type": "date"}}
857
- ],
858
- "foo": "bar"
859
- }),
860
- %q(
861
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
862
- [ <http://example.org/foo#> "bar"^^xsd:date ] .
863
- )
864
- ],
865
- "@id with term" => [
866
- %q({
867
- "@context": [
868
- {"foo": {"@id": "http://example.org/foo#bar", "@type": "@id"}}
869
- ],
870
- "foo": "http://example.org/foo#bar"
871
- }),
872
- %q(
873
- _:a <http://example.org/foo#bar> <http://example.org/foo#bar> .
874
- )
875
- ],
876
- "coercion without term definition" => [
877
- %q({
878
- "@context": [
879
- {
880
- "xsd": "http://www.w3.org/2001/XMLSchema#",
881
- "dc": "http://purl.org/dc/terms/"
882
- },
883
- {
884
- "dc:date": {"@type": "xsd:date"}
885
- }
886
- ],
887
- "dc:date": "2011-11-23"
888
- }),
889
- %q(
890
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
891
- @prefix dc: <http://purl.org/dc/terms/> .
892
- [ dc:date "2011-11-23"^^xsd:date] .
893
- )
894
- ],
895
- }.each do |title, (js, ttl)|
896
- it title do
897
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
898
- expect(parse(js)).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
899
- end
900
- end
901
- end
902
- end
903
-
904
- context "lists" do
905
- context "term def with @id + @type + @container" do
906
- {
907
- "dt with term" => [
908
- %q({
909
- "@context": [
910
- {"date": "http://www.w3.org/2001/XMLSchema#date", "term": "http://example.org/foo#"},
911
- {"foo": {"@id": "term", "@type": "date", "@container": "@list"}}
912
- ],
913
- "foo": ["bar"]
914
- }),
915
- %q(
916
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
917
- [ <http://example.org/foo#> ("bar"^^xsd:date) ] .
918
- )
919
- ],
920
- "@id with term" => [
921
- %q({
922
- "@context": [
923
- {"foo": {"@id": "http://example.org/foo#bar", "@type": "@id", "@container": "@list"}}
924
- ],
925
- "foo": ["http://example.org/foo#bar"]
926
- }),
927
- %q(
928
- _:a <http://example.org/foo#bar> (<http://example.org/foo#bar>) .
929
- )
930
- ],
931
- }.each do |title, (js, ttl)|
932
- it title do
933
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
934
- expect(parse(js)).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
935
- end
936
- end
937
- end
938
- end
939
- end
940
-
941
- context "blank node predicates" do
942
- subject {%q({"@id": "http://example/subj", "_:foo": "bar"})}
943
-
944
- it "outputs statements with blank node predicates if :produceGeneralizedRdf is true" do
945
- expect do
946
- graph = parse(subject, produceGeneralizedRdf: true)
947
- expect(graph.count).to eq 1
948
- end.to write("[DEPRECATION]").to(:error)
949
- end
950
-
951
- it "rejects statements with blank node predicates if :produceGeneralizedRdf is false" do
952
- expect do
953
- graph = parse(subject, produceGeneralizedRdf: false)
954
- expect(graph.count).to eq 0
955
- end.to write("[DEPRECATION]").to(:error)
956
- end
957
- end
958
-
959
- context "@included" do
960
- {
961
- "Basic Included array": {
962
- input: %({
963
- "@context": {
964
- "@version": 1.1,
965
- "@vocab": "http://example.org/"
966
- },
967
- "prop": "value",
968
- "@included": [{
969
- "prop": "value2"
970
- }]
971
- }),
972
- output: %(
973
- [<http://example.org/prop> "value"] .
974
- [<http://example.org/prop> "value2"] .
975
- )
976
- },
977
- "Basic Included object": {
978
- input: %({
979
- "@context": {
980
- "@version": 1.1,
981
- "@vocab": "http://example.org/"
982
- },
983
- "prop": "value",
984
- "@included": {
985
- "prop": "value2"
986
- }
987
- }),
988
- output: %(
989
- [<http://example.org/prop> "value"] .
990
- [<http://example.org/prop> "value2"] .
991
- )
992
- },
993
- "Multiple properties mapping to @included are folded together": {
994
- input: %({
995
- "@context": {
996
- "@version": 1.1,
997
- "@vocab": "http://example.org/",
998
- "included1": "@included",
999
- "included2": "@included"
1000
- },
1001
- "included1": {"prop": "value1"},
1002
- "included2": {"prop": "value2"}
1003
- }),
1004
- output: %(
1005
- [<http://example.org/prop> "value1"] .
1006
- [<http://example.org/prop> "value2"] .
1007
- )
1008
- },
1009
- "Included containing @included": {
1010
- input: %({
1011
- "@context": {
1012
- "@version": 1.1,
1013
- "@vocab": "http://example.org/"
1014
- },
1015
- "prop": "value",
1016
- "@included": {
1017
- "prop": "value2",
1018
- "@included": {
1019
- "prop": "value3"
1020
- }
1021
- }
1022
- }),
1023
- output: %(
1024
- [<http://example.org/prop> "value"] .
1025
-
1026
- [<http://example.org/prop> "value2"] .
1027
-
1028
- [<http://example.org/prop> "value3"] .
1029
- )
1030
- },
1031
- "Property value with @included": {
1032
- input: %({
1033
- "@context": {
1034
- "@version": 1.1,
1035
- "@vocab": "http://example.org/"
1036
- },
1037
- "prop": {
1038
- "@type": "Foo",
1039
- "@included": {
1040
- "@type": "Bar"
1041
- }
1042
- }
1043
- }),
1044
- output: %(
1045
- [<http://example.org/prop> [a <http://example.org/Foo>]] .
1046
- [a <http://example.org/Bar>] .
1047
- )
1048
- },
1049
- "json.api example": {
1050
- input: %({
1051
- "@context": {
1052
- "@version": 1.1,
1053
- "@vocab": "http://example.org/vocab#",
1054
- "@base": "http://example.org/base/",
1055
- "id": "@id",
1056
- "type": "@type",
1057
- "data": "@nest",
1058
- "attributes": "@nest",
1059
- "links": "@nest",
1060
- "relationships": "@nest",
1061
- "included": "@included",
1062
- "self": {"@type": "@id"},
1063
- "related": {"@type": "@id"},
1064
- "comments": {
1065
- "@context": {
1066
- "data": null
1067
- }
1068
- }
1069
- },
1070
- "data": [{
1071
- "type": "articles",
1072
- "id": "1",
1073
- "attributes": {
1074
- "title": "JSON:API paints my bikeshed!"
1075
- },
1076
- "links": {
1077
- "self": "http://example.com/articles/1"
1078
- },
1079
- "relationships": {
1080
- "author": {
1081
- "links": {
1082
- "self": "http://example.com/articles/1/relationships/author",
1083
- "related": "http://example.com/articles/1/author"
1084
- },
1085
- "data": { "type": "people", "id": "9" }
1086
- },
1087
- "comments": {
1088
- "links": {
1089
- "self": "http://example.com/articles/1/relationships/comments",
1090
- "related": "http://example.com/articles/1/comments"
1091
- },
1092
- "data": [
1093
- { "type": "comments", "id": "5" },
1094
- { "type": "comments", "id": "12" }
1095
- ]
1096
- }
1097
- }
1098
- }],
1099
- "included": [{
1100
- "type": "people",
1101
- "id": "9",
1102
- "attributes": {
1103
- "first-name": "Dan",
1104
- "last-name": "Gebhardt",
1105
- "twitter": "dgeb"
1106
- },
1107
- "links": {
1108
- "self": "http://example.com/people/9"
1109
- }
1110
- }, {
1111
- "type": "comments",
1112
- "id": "5",
1113
- "attributes": {
1114
- "body": "First!"
1115
- },
1116
- "relationships": {
1117
- "author": {
1118
- "data": { "type": "people", "id": "2" }
1119
- }
1120
- },
1121
- "links": {
1122
- "self": "http://example.com/comments/5"
1123
- }
1124
- }, {
1125
- "type": "comments",
1126
- "id": "12",
1127
- "attributes": {
1128
- "body": "I like XML better"
1129
- },
1130
- "relationships": {
1131
- "author": {
1132
- "data": { "type": "people", "id": "9" }
1133
- }
1134
- },
1135
- "links": {
1136
- "self": "http://example.com/comments/12"
1137
- }
1138
- }]
1139
- }),
1140
- output: %(
1141
- <http://example.org/base/1> a <http://example.org/vocab#articles>;
1142
- <http://example.org/vocab#author> <http://example.org/base/9>;
1143
- <http://example.org/vocab#comments> [
1144
- <http://example.org/vocab#related> <http://example.com/articles/1/comments>;
1145
- <http://example.org/vocab#self> <http://example.com/articles/1/relationships/comments>
1146
- ];
1147
- <http://example.org/vocab#self> <http://example.com/articles/1>;
1148
- <http://example.org/vocab#title> "JSON:API paints my bikeshed!" .
1149
-
1150
- <http://example.org/base/12> a <http://example.org/vocab#comments>;
1151
- <http://example.org/vocab#author> <http://example.org/base/9>;
1152
- <http://example.org/vocab#body> "I like XML better";
1153
- <http://example.org/vocab#self> <http://example.com/comments/12> .
1154
-
1155
- <http://example.org/base/5> a <http://example.org/vocab#comments>;
1156
- <http://example.org/vocab#author> <http://example.org/base/2>;
1157
- <http://example.org/vocab#body> "First!";
1158
- <http://example.org/vocab#self> <http://example.com/comments/5> .
1159
-
1160
- <http://example.org/base/2> a <http://example.org/vocab#people> .
1161
-
1162
- <http://example.org/base/9> a <http://example.org/vocab#people>;
1163
- <http://example.org/vocab#first-name> "Dan";
1164
- <http://example.org/vocab#last-name> "Gebhardt";
1165
- <http://example.org/vocab#related> <http://example.com/articles/1/author>;
1166
- <http://example.org/vocab#self> <http://example.com/articles/1/relationships/author>,
1167
- <http://example.com/people/9>;
1168
- <http://example.org/vocab#twitter> "dgeb" .
1169
- )
1170
- },
1171
- }.each do |title, params|
1172
- it(title) {run_to_rdf params}
1173
- end
1174
- end
1175
-
1176
- context "advanced features" do
1177
- {
1178
- "number syntax (decimal)" =>
1179
- [
1180
- %q({"@context": { "measure": "http://example/measure#"}, "measure:cups": 5.3}),
1181
- %q(_:a <http://example/measure#cups> "5.3E0"^^<http://www.w3.org/2001/XMLSchema#double> .)
1182
- ],
1183
- "number syntax (double)" =>
1184
- [
1185
- %q({"@context": { "measure": "http://example/measure#"}, "measure:cups": 5.3e0}),
1186
- %q(_:a <http://example/measure#cups> "5.3E0"^^<http://www.w3.org/2001/XMLSchema#double> .)
1187
- ],
1188
- "number syntax (integer)" =>
1189
- [
1190
- %q({"@context": { "chem": "http://example/chem#"}, "chem:protons": 12}),
1191
- %q(_:a <http://example/chem#protons> "12"^^<http://www.w3.org/2001/XMLSchema#integer> .)
1192
- ],
1193
- "boolan syntax" =>
1194
- [
1195
- %q({"@context": { "sensor": "http://example/sensor#"}, "sensor:active": true}),
1196
- %q(_:a <http://example/sensor#active> "true"^^<http://www.w3.org/2001/XMLSchema#boolean> .)
1197
- ],
1198
- "Array top element" =>
1199
- [
1200
- %q([
1201
- {"@id": "http://example.com/#me", "@type": "http://xmlns.com/foaf/0.1/Person"},
1202
- {"@id": "http://example.com/#you", "@type": "http://xmlns.com/foaf/0.1/Person"}
1203
- ]),
1204
- %q(
1205
- <http://example.com/#me> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .
1206
- <http://example.com/#you> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .
1207
- )
1208
- ],
1209
- "@graph with array of objects value" =>
1210
- [
1211
- %q({
1212
- "@context": {"foaf": "http://xmlns.com/foaf/0.1/"},
1213
- "@graph": [
1214
- {"@id": "http://example.com/#me", "@type": "foaf:Person"},
1215
- {"@id": "http://example.com/#you", "@type": "foaf:Person"}
1216
- ]
1217
- }),
1218
- %q(
1219
- <http://example.com/#me> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .
1220
- <http://example.com/#you> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .
1221
- )
1222
- ],
1223
- "XMLLiteral" => [
1224
- %q({
1225
- "http://rdfs.org/sioc/ns#content": {
1226
- "@value": "foo",
1227
- "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral"
1228
- }
1229
- }),
1230
- %q(
1231
- [<http://rdfs.org/sioc/ns#content> "foo"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral>] .
1232
- )
1233
- ],
1234
- }.each do |title, (js, ttl)|
1235
- it title do
1236
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
1237
- expect(parse(js)).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
1238
- end
1239
- end
1240
- end
1241
-
1242
- context "@direction" do
1243
- context "rdfDirection: null" do
1244
- {
1245
- "no language rtl": [
1246
- %q({"http://example.org/label": {"@value": "no language", "@direction": "rtl"}}),
1247
- %q(_:a <http://example.org/label> "no language" .)
1248
- ],
1249
- "en-US rtl": [
1250
- %q({"http://example.org/label": {"@value": "en-US", "@language": "en-US", "@direction": "rtl"}}),
1251
- %q(_:a <http://example.org/label> "en-US"@en-us .)
1252
- ]
1253
- }.each do |title, (js, ttl)|
1254
- it title do
1255
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
1256
- expect(parse(js, rdfDirection: nil)).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
1257
- end
1258
- end
1259
- end
1260
-
1261
- context "rdfDirection: i18n-datatype" do
1262
- {
1263
- "no language rtl": [
1264
- %q({"http://example.org/label": {"@value": "no language", "@direction": "rtl"}}),
1265
- %q(_:a <http://example.org/label> "no language"^^<https://www.w3.org/ns/i18n#_rtl> .)
1266
- ],
1267
- "en-US rtl": [
1268
- %q({"http://example.org/label": {"@value": "en-US", "@language": "en-US", "@direction": "rtl"}}),
1269
- %q(_:a <http://example.org/label> "en-US"^^<https://www.w3.org/ns/i18n#en-us_rtl> .)
1270
- ]
1271
- }.each do |title, (js, ttl)|
1272
- it title do
1273
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
1274
- expect(parse(js, rdfDirection: 'i18n-datatype')).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
1275
- end
1276
- end
1277
- end
1278
-
1279
- context "rdfDirection: compound-literal" do
1280
- {
1281
- "no language rtl": [
1282
- %q({"http://example.org/label": {"@value": "no language", "@direction": "rtl"}}),
1283
- %q(
1284
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
1285
- _:a <http://example.org/label> [
1286
- rdf:value "no language";
1287
- rdf:direction "rtl"
1288
- ] .
1289
- )
1290
- ],
1291
- "en-US rtl": [
1292
- %q({"http://example.org/label": {"@value": "en-US", "@language": "en-US", "@direction": "rtl"}}),
1293
- %q(
1294
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
1295
- _:a <http://example.org/label> [
1296
- rdf:value "en-US";
1297
- rdf:language "en-us";
1298
- rdf:direction "rtl"
1299
- ] .
1300
- )
1301
- ]
1302
- }.each do |title, (js, ttl)|
1303
- it title do
1304
- ttl = "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . #{ttl}"
1305
- expect(parse(js, rdfDirection: 'compound-literal')).to be_equivalent_graph(ttl, logger: logger, inputDocument: js)
1306
- end
1307
- end
1308
- end
1309
- end
1310
-
1311
- context "JSON-LD-star" do
1312
- {
1313
- "node with embedded subject without rdfstar option": {
1314
- input: %({
1315
- "@id": {
1316
- "@id": "ex:rei",
1317
- "ex:prop": "value"
1318
- },
1319
- "ex:prop": "value2"
1320
- }),
1321
- exception: JSON::LD::JsonLdError::InvalidIdValue
1322
- },
1323
- }.each do |title, params|
1324
- it(title) {run_to_rdf params}
1325
- end
1326
-
1327
- {
1328
- "node with embedded subject having no @id": {
1329
- input: %({
1330
- "@id": {
1331
- "ex:prop": "value"
1332
- },
1333
- "ex:prop": "value2"
1334
- }),
1335
- expected: %(
1336
- <<_:b0 <ex:prop> "value">> <ex:prop> "value2" .
1337
- ),
1338
- },
1339
- "node with embedded subject having IRI @id": {
1340
- input: %({
1341
- "@id": {
1342
- "@id": "ex:rei",
1343
- "ex:prop": "value"
1344
- },
1345
- "ex:prop": "value2"
1346
- }),
1347
- expected: %(
1348
- <<<ex:rei> <ex:prop> "value">> <ex:prop> "value2" .
1349
- ),
1350
- },
1351
- "node with embedded subject having BNode @id": {
1352
- input: %({
1353
- "@id": {
1354
- "@id": "_:rei",
1355
- "ex:prop": "value"
1356
- },
1357
- "ex:prop": "value2"
1358
- }),
1359
- expected: %(
1360
- <<_:b0 <ex:prop> "value">> <ex:prop> "value2" .
1361
- ),
1362
- },
1363
- "node with embedded subject having a type": {
1364
- input: %({
1365
- "@id": {
1366
- "@id": "ex:rei",
1367
- "@type": "ex:Type"
1368
- },
1369
- "ex:prop": "value2"
1370
- }),
1371
- expected: %(
1372
- <<<ex:rei> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <ex:Type>>> <ex:prop> "value2" .
1373
- ),
1374
- },
1375
- "node with embedded subject having an IRI value": {
1376
- input: %({
1377
- "@id": {
1378
- "@id": "ex:rei",
1379
- "ex:prop": {"@id": "ex:value"}
1380
- },
1381
- "ex:prop": "value2"
1382
- }),
1383
- expected: %(
1384
- <<<ex:rei> <ex:prop> <ex:value>>> <ex:prop> "value2" .
1385
- ),
1386
- },
1387
- "node with embedded subject having an BNode value": {
1388
- input: %({
1389
- "@id": {
1390
- "@id": "ex:rei",
1391
- "ex:prop": {"@id": "_:value"}
1392
- },
1393
- "ex:prop": "value2"
1394
- }),
1395
- expected: %(
1396
- <<<ex:rei> <ex:prop> _:b0>> <ex:prop> "value2" .
1397
- ),
1398
- },
1399
- "node with recursive embedded subject": {
1400
- input: %({
1401
- "@id": {
1402
- "@id": {
1403
- "@id": "ex:rei",
1404
- "ex:prop": "value3"
1405
- },
1406
- "ex:prop": "value"
1407
- },
1408
- "ex:prop": "value2"
1409
- }),
1410
- expected: %(
1411
- <<<<<ex:rei> <ex:prop> "value3">> <ex:prop> "value">> <ex:prop> "value2" .
1412
- ),
1413
- },
1414
- "illegal node with subject having no property": {
1415
- input: %({
1416
- "@id": {
1417
- "@id": "ex:rei"
1418
- },
1419
- "ex:prop": "value3"
1420
- }),
1421
- exception: JSON::LD::JsonLdError::InvalidEmbeddedNode
1422
- },
1423
- "illegal node with subject having multiple properties": {
1424
- input: %({
1425
- "@id": {
1426
- "@id": "ex:rei",
1427
- "ex:prop": ["value1", "value2"]
1428
- },
1429
- "ex:prop": "value3"
1430
- }),
1431
- exception: JSON::LD::JsonLdError::InvalidEmbeddedNode
1432
- },
1433
- "illegal node with subject having multiple types": {
1434
- input: %({
1435
- "@id": {
1436
- "@id": "ex:rei",
1437
- "@type": ["ex:Type1", "ex:Type2"]
1438
- },
1439
- "ex:prop": "value3"
1440
- }),
1441
- exception: JSON::LD::JsonLdError::InvalidEmbeddedNode
1442
- },
1443
- "illegal node with subject having type and property": {
1444
- input: %({
1445
- "@id": {
1446
- "@id": "ex:rei",
1447
- "@type": "ex:Type",
1448
- "ex:prop": "value"
1449
- },
1450
- "ex:prop": "value2"
1451
- }),
1452
- exception: JSON::LD::JsonLdError::InvalidEmbeddedNode
1453
- },
1454
- "node with embedded object": {
1455
- input: %({
1456
- "@id": "ex:subj",
1457
- "ex:value": {
1458
- "@id": {
1459
- "@id": "ex:rei",
1460
- "ex:prop": "value"
1461
- }
1462
- }
1463
- }),
1464
- expected: %(
1465
- <ex:subj> <ex:value> <<<ex:rei> <ex:prop> "value">> .
1466
- ),
1467
- },
1468
- "node with embedded object having properties": {
1469
- input: %({
1470
- "@id": "ex:subj",
1471
- "ex:value": {
1472
- "@id": {
1473
- "@id": "ex:rei",
1474
- "ex:prop": "value"
1475
- },
1476
- "ex:prop": "value2"
1477
- }
1478
- }),
1479
- expected: %(
1480
- <ex:subj> <ex:value> <<<ex:rei> <ex:prop> "value">> .
1481
- <<<ex:rei> <ex:prop> "value">> <ex:prop> "value2" .
1482
- ),
1483
- },
1484
- "node with recursive embedded object": {
1485
- input: %({
1486
- "@id": "ex:subj",
1487
- "ex:value": {
1488
- "@id": {
1489
- "@id": {
1490
- "@id": "ex:rei",
1491
- "ex:prop": "value3"
1492
- },
1493
- "ex:prop": "value"
1494
- },
1495
- "ex:prop": "value2"
1496
- }
1497
- }),
1498
- expected: %(
1499
- <ex:subj> <ex:value> <<<<<ex:rei> <ex:prop> "value3">> <ex:prop> "value">> .
1500
- <<<<<ex:rei> <ex:prop> "value3">> <ex:prop> "value">> <ex:prop> "value2" .
1501
- ),
1502
- },
1503
- }.each do |title, params|
1504
- context(title) do
1505
- it "Generates statements" do
1506
- output_graph = RDF::Graph.new {|g| g << RDF::NTriples::Reader.new(params[:expected], rdfstar: true)}
1507
- run_to_rdf params.merge(rdfstar: true, output: output_graph)
1508
- end if params[:expected]
1509
-
1510
- it "Exception" do
1511
- run_to_rdf params.merge(rdfstar: true)
1512
- end if params[:exception]
1513
- end
1514
- end
1515
- end
1516
-
1517
- context "exceptions" do
1518
- {
1519
- "Invalid subject" => {
1520
- input: %({
1521
- "@id": "http://example.com/a b",
1522
- "http://example.com/foo": "bar"
1523
- }),
1524
- output: %()
1525
- },
1526
- "Invalid predicate" => {
1527
- input: %({
1528
- "@id": "http://example.com/foo",
1529
- "http://example.com/a b": "bar"
1530
- }),
1531
- output: %()
1532
- },
1533
- "Invalid object" => {
1534
- input: %({
1535
- "@id": "http://example.com/foo",
1536
- "http://example.com/bar": {"@id": "http://example.com/baz z"}
1537
- }),
1538
- output: %()
1539
- },
1540
- "Invalid type" => {
1541
- input: %({
1542
- "@id": "http://example.com/foo",
1543
- "@type": ["http://example.com/bar", "relative"]
1544
- }),
1545
- output: %(<http://example.com/foo> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.com/bar> .)
1546
- },
1547
- "Invalid language" => {
1548
- input: %({
1549
- "@id": "http://example.com/foo",
1550
- "http://example.com/bar": {"@value": "bar", "@language": "a b"}
1551
- }),
1552
- output: %(),
1553
- write: "@language must be valid BCP47"
1554
- },
1555
- "Invalid datatype" => {
1556
- input: %({
1557
- "@id": "http://example.com/foo",
1558
- "http://example.com/bar": {"@value": "bar", "@type": "http://example.com/baz z"}
1559
- }),
1560
- exception: JSON::LD::JsonLdError::InvalidTypedValue
1561
- },
1562
- "Injected IRIs check" => {
1563
- input: %({
1564
- "@id": "http://foo/> <http://bar/> <http://baz> .\n<data:little> <data:bobby> <data:tables> .\n<data:in-ur-base",
1565
- "http://killin/#yer": "dudes"
1566
- }),
1567
- output: %(),
1568
- pending: "jruby"
1569
- },
1570
- }.each do |title, params|
1571
- it(title) do
1572
- pending params[:pending] if params[:pending] == RUBY_ENGINE
1573
- run_to_rdf params
1574
- end
1575
- end
1576
- end
1577
- end
1578
-
1579
- context "html" do
1580
- {
1581
- "Transforms embedded JSON-LD script element": {
1582
- input: %(
1583
- <html>
1584
- <head>
1585
- <script type="application/ld+json">
1586
- {
1587
- "@context": {
1588
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
1589
- },
1590
- "foo": [{"@value": "bar"}]
1591
- }
1592
- </script>
1593
- </head>
1594
- </html>),
1595
- output: %([ <http://example.com/foo> ( "bar")] .)
1596
- },
1597
- "Transforms first script element with extractAllScripts: false": {
1598
- input: %(
1599
- <html>
1600
- <head>
1601
- <script type="application/ld+json">
1602
- {
1603
- "@context": {
1604
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
1605
- },
1606
- "foo": [{"@value": "bar"}]
1607
- }
1608
- </script>
1609
- <script type="application/ld+json">
1610
- {
1611
- "@context": {"ex": "http://example.com/"},
1612
- "@graph": [
1613
- {"ex:foo": {"@value": "foo"}},
1614
- {"ex:bar": {"@value": "bar"}}
1615
- ]
1616
- }
1617
- </script>
1618
- </head>
1619
- </html>),
1620
- output: %([ <http://example.com/foo> ( "bar")] .),
1621
- extractAllScripts: false
1622
- },
1623
- "Transforms targeted script element": {
1624
- input: %(
1625
- <html>
1626
- <head>
1627
- <script id="first" type="application/ld+json">
1628
- {
1629
- "@context": {
1630
- "foo": {"@id": "http://example.com/foo", "@container": "@list"}
1631
- },
1632
- "foo": [{"@value": "bar"}]
1633
- }
1634
- </script>
1635
- <script id="second" type="application/ld+json">
1636
- {
1637
- "@context": {"ex": "http://example.com/"},
1638
- "@graph": [
1639
- {"ex:foo": {"@value": "foo"}},
1640
- {"ex:bar": {"@value": "bar"}}
1641
- ]
1642
- }
1643
- </script>
1644
- </head>
1645
- </html>),
1646
- output: %(
1647
- [ <http://example.com/foo> "foo"] .
1648
- [ <http://example.com/bar> "bar"] .
1649
- ),
1650
- base: "http://example.org/doc#second"
1651
- },
1652
- }.each do |title, params|
1653
- it(title) do
1654
- params[:input] = StringIO.new(params[:input])
1655
- params[:input].send(:define_singleton_method, :content_type) {"text/html"}
1656
- run_to_rdf params.merge(validate: true)
1657
- end
1658
- end
1659
- end
1660
-
1661
- def parse(input, **options)
1662
- graph = options[:graph] || RDF::Graph.new
1663
- options = {logger: logger, validate: true, canonicalize: false}.merge(options)
1664
- JSON::LD::API.toRdf(StringIO.new(input), rename_bnodes: false, **options) {|st| graph << st}
1665
- graph
1666
- end
1667
-
1668
- def run_to_rdf(params)
1669
- input, output = params[:input], params[:output]
1670
- graph = params[:graph] || RDF::Graph.new
1671
- input = StringIO.new(input) if input.is_a?(String)
1672
- pending params.fetch(:pending, "test implementation") unless input
1673
- if params[:exception]
1674
- expect {JSON::LD::API.toRdf(input, **params)}.to raise_error(params[:exception])
1675
- else
1676
- if params[:write]
1677
- expect{JSON::LD::API.toRdf(input, base: params[:base], logger: logger, rename_bnodes: false, **params) {|st| graph << st}}.to write(params[:write]).to(:error)
1678
- else
1679
- expect{JSON::LD::API.toRdf(input, base: params[:base], logger: logger, rename_bnodes: false, **params) {|st| graph << st}}.not_to write.to(:error)
1680
- end
1681
- expect(graph).to be_equivalent_graph(output, logger: logger, inputDocument: input)
1682
- end
1683
- end
1684
- end