json-ld 3.0.2 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHORS +1 -1
  3. data/README.md +90 -53
  4. data/UNLICENSE +1 -1
  5. data/VERSION +1 -1
  6. data/bin/jsonld +4 -4
  7. data/lib/json/ld.rb +27 -10
  8. data/lib/json/ld/api.rb +325 -96
  9. data/lib/json/ld/compact.rb +75 -27
  10. data/lib/json/ld/conneg.rb +188 -0
  11. data/lib/json/ld/context.rb +677 -292
  12. data/lib/json/ld/expand.rb +240 -75
  13. data/lib/json/ld/flatten.rb +5 -3
  14. data/lib/json/ld/format.rb +19 -19
  15. data/lib/json/ld/frame.rb +135 -85
  16. data/lib/json/ld/from_rdf.rb +44 -17
  17. data/lib/json/ld/html/nokogiri.rb +151 -0
  18. data/lib/json/ld/html/rexml.rb +186 -0
  19. data/lib/json/ld/reader.rb +25 -5
  20. data/lib/json/ld/resource.rb +2 -2
  21. data/lib/json/ld/streaming_writer.rb +3 -1
  22. data/lib/json/ld/to_rdf.rb +47 -17
  23. data/lib/json/ld/utils.rb +4 -2
  24. data/lib/json/ld/writer.rb +75 -14
  25. data/spec/api_spec.rb +13 -34
  26. data/spec/compact_spec.rb +968 -9
  27. data/spec/conneg_spec.rb +373 -0
  28. data/spec/context_spec.rb +447 -53
  29. data/spec/expand_spec.rb +1872 -416
  30. data/spec/flatten_spec.rb +434 -47
  31. data/spec/frame_spec.rb +979 -344
  32. data/spec/from_rdf_spec.rb +305 -5
  33. data/spec/spec_helper.rb +177 -0
  34. data/spec/streaming_writer_spec.rb +4 -4
  35. data/spec/suite_compact_spec.rb +2 -2
  36. data/spec/suite_expand_spec.rb +14 -2
  37. data/spec/suite_flatten_spec.rb +10 -2
  38. data/spec/suite_frame_spec.rb +3 -2
  39. data/spec/suite_from_rdf_spec.rb +2 -2
  40. data/spec/suite_helper.rb +55 -20
  41. data/spec/suite_html_spec.rb +22 -0
  42. data/spec/suite_http_spec.rb +35 -0
  43. data/spec/suite_remote_doc_spec.rb +2 -2
  44. data/spec/suite_to_rdf_spec.rb +14 -3
  45. data/spec/support/extensions.rb +5 -1
  46. data/spec/test-files/test-4-input.json +3 -3
  47. data/spec/test-files/test-5-input.json +2 -2
  48. data/spec/test-files/test-8-framed.json +14 -18
  49. data/spec/to_rdf_spec.rb +606 -16
  50. data/spec/writer_spec.rb +5 -5
  51. metadata +144 -88
@@ -6,7 +6,7 @@ describe JSON::LD::API do
6
6
 
7
7
  describe ".frame" do
8
8
  {
9
- "exact @type match" => {
9
+ "exact @type match": {
10
10
  frame: %({
11
11
  "@context": {"ex": "http://example.org/"},
12
12
  "@type": "ex:Type1"
@@ -30,7 +30,7 @@ describe JSON::LD::API do
30
30
  }]
31
31
  })
32
32
  },
33
- "wildcard @type match" => {
33
+ "wildcard @type match": {
34
34
  frame: %({
35
35
  "@context": {"ex": "http://example.org/"},
36
36
  "@type": {}
@@ -57,7 +57,7 @@ describe JSON::LD::API do
57
57
  }]
58
58
  })
59
59
  },
60
- "match none @type match" => {
60
+ "match none @type match": {
61
61
  frame: %({
62
62
  "@context": {"ex": "http://example.org/"},
63
63
  "@type": []
@@ -82,7 +82,7 @@ describe JSON::LD::API do
82
82
  }]
83
83
  })
84
84
  },
85
- "multiple matches on @type" => {
85
+ "multiple matches on @type": {
86
86
  frame: %({
87
87
  "@context": {"ex": "http://example.org/"},
88
88
  "@type": "ex:Type1"
@@ -114,7 +114,7 @@ describe JSON::LD::API do
114
114
  }]
115
115
  })
116
116
  },
117
- "single @id match" => {
117
+ "single @id match": {
118
118
  frame: %({
119
119
  "@context": {"ex": "http://example.org/"},
120
120
  "@id": "ex:Sub1"
@@ -138,7 +138,7 @@ describe JSON::LD::API do
138
138
  }]
139
139
  })
140
140
  },
141
- "multiple @id match" => {
141
+ "multiple @id match": {
142
142
  frame: %({
143
143
  "@context": {"ex": "http://example.org/"},
144
144
  "@id": ["ex:Sub1", "ex:Sub2"]
@@ -169,7 +169,7 @@ describe JSON::LD::API do
169
169
  }]
170
170
  })
171
171
  },
172
- "wildcard and match none" => {
172
+ "wildcard and match none": {
173
173
  frame: %({
174
174
  "@context": {"ex": "http://example.org/"},
175
175
  "ex:p": [],
@@ -196,7 +196,7 @@ describe JSON::LD::API do
196
196
  }]
197
197
  })
198
198
  },
199
- "match on any property if @requireAll is false" => {
199
+ "match on any property if @requireAll is false": {
200
200
  frame: %({
201
201
  "@context": {"ex": "http://example.org/"},
202
202
  "@requireAll": false,
@@ -227,7 +227,7 @@ describe JSON::LD::API do
227
227
  }]
228
228
  })
229
229
  },
230
- "match on defeaults if @requireAll is true and at least one property matches" => {
230
+ "match on defeaults if @requireAll is true and at least one property matches": {
231
231
  frame: %({
232
232
  "@context": {"ex": "http://example.org/"},
233
233
  "@requireAll": true,
@@ -271,7 +271,7 @@ describe JSON::LD::API do
271
271
  }]
272
272
  })
273
273
  },
274
- "match with @requireAll with one default" => {
274
+ "match with @requireAll with one default": {
275
275
  frame: %({
276
276
  "@context": {"ex": "http://example.org/"},
277
277
  "@requireAll": true,
@@ -307,7 +307,117 @@ describe JSON::LD::API do
307
307
  }]
308
308
  })
309
309
  },
310
- "implicitly includes unframed properties (default @explicit false)" => {
310
+ "don't match with @requireAll, matching @type but no matching property": {
311
+ frame: %({
312
+ "@context": {"ex": "http://example.org/"},
313
+ "@requireAll": true,
314
+ "@type": "ex:Type",
315
+ "ex:p": {}
316
+ }),
317
+ input: %([
318
+ {
319
+ "@context": {"ex": "http://example.org/"},
320
+ "@id": "ex:Sub1",
321
+ "@type": "ex:Type",
322
+ "ex:p": "foo"
323
+ }, {
324
+ "@context": { "ex":"http://example.org/"},
325
+ "@id": "ex:Sub2",
326
+ "@type": "ex:Type"
327
+ }, {
328
+ "@context": { "ex":"http://example.org/"},
329
+ "@id": "ex:Sub3",
330
+ "ex:p": "foo"
331
+ }
332
+ ]),
333
+ output: %({
334
+ "@context": {"ex": "http://example.org/"},
335
+ "@graph": [{
336
+ "@id": "ex:Sub1",
337
+ "@type": "ex:Type",
338
+ "ex:p": "foo"
339
+ }]
340
+ })
341
+ },
342
+ "don't match with @requireAll, matching @id but no matching @type": {
343
+ frame: %({
344
+ "@context": {"ex": "http://example.org/"},
345
+ "@requireAll": true,
346
+ "@id": ["ex:Sub1", "ex:Sub2"],
347
+ "@type": "ex:Type"
348
+ }),
349
+ input: %([
350
+ {
351
+ "@context": {"ex": "http://example.org/"},
352
+ "@id": "ex:Sub1",
353
+ "@type": "ex:Type",
354
+ "ex:p": "foo"
355
+ }, {
356
+ "@context": { "ex":"http://example.org/"},
357
+ "@id": "ex:Sub2",
358
+ "@type": "ex:OtherType"
359
+ }, {
360
+ "@context": { "ex":"http://example.org/"},
361
+ "@id": "ex:Sub3",
362
+ "@type": "ex:Type",
363
+ "ex:p": "foo"
364
+ }
365
+ ]),
366
+ output: %({
367
+ "@context": {"ex": "http://example.org/"},
368
+ "@graph": [{
369
+ "@id": "ex:Sub1",
370
+ "@type": "ex:Type",
371
+ "ex:p": "foo"
372
+ }]
373
+ })
374
+ },
375
+ "issue #40 - example": {
376
+ frame: %({
377
+ "@context": {
378
+ "@version": 1.1,
379
+ "@vocab": "https://schema.org/"
380
+ },
381
+ "@type": "Person",
382
+ "@requireAll": true,
383
+ "givenName": "John",
384
+ "familyName": "Doe"
385
+ }),
386
+ input: %({
387
+ "@context": {
388
+ "@version": 1.1,
389
+ "@vocab": "https://schema.org/"
390
+ },
391
+ "@graph": [
392
+ {
393
+ "@id": "1",
394
+ "@type": "Person",
395
+ "name": "John Doe",
396
+ "givenName": "John",
397
+ "familyName": "Doe"
398
+ },
399
+ {
400
+ "@id": "2",
401
+ "@type": "Person",
402
+ "name": "Jane Doe",
403
+ "givenName": "Jane"
404
+ }
405
+ ]
406
+ }),
407
+ output: %({
408
+ "@context": {
409
+ "@version": 1.1,
410
+ "@vocab": "https://schema.org/"
411
+ },
412
+ "@id": "1",
413
+ "@type": "Person",
414
+ "familyName": "Doe",
415
+ "givenName": "John",
416
+ "name": "John Doe"
417
+ }),
418
+ processingMode: 'json-ld-1.1'
419
+ },
420
+ "implicitly includes unframed properties (default @explicit false)": {
311
421
  frame: %({
312
422
  "@context": {"ex": "http://example.org/"},
313
423
  "@type": "ex:Type1"
@@ -329,7 +439,7 @@ describe JSON::LD::API do
329
439
  }]
330
440
  })
331
441
  },
332
- "explicitly includes unframed properties @explicit false" => {
442
+ "explicitly includes unframed properties @explicit false": {
333
443
  frame: %({
334
444
  "@context": {"ex": "http://example.org/"},
335
445
  "@explicit": false,
@@ -352,7 +462,7 @@ describe JSON::LD::API do
352
462
  }]
353
463
  })
354
464
  },
355
- "explicitly excludes unframed properties (@explicit: true)" => {
465
+ "explicitly excludes unframed properties (@explicit: true)": {
356
466
  frame: %({
357
467
  "@context": {"ex": "http://example.org/"},
358
468
  "@explicit": true,
@@ -373,7 +483,7 @@ describe JSON::LD::API do
373
483
  }]
374
484
  })
375
485
  },
376
- "non-existent framed properties create null property" => {
486
+ "non-existent framed properties create null property": {
377
487
  frame: %({
378
488
  "@context": {"ex": "http://example.org/"},
379
489
  "@type": "ex:Type1",
@@ -401,7 +511,7 @@ describe JSON::LD::API do
401
511
  }]
402
512
  })
403
513
  },
404
- "non-existent framed properties create default property" => {
514
+ "non-existent framed properties create default property": {
405
515
  frame: %({
406
516
  "@context": {
407
517
  "ex": "http://example.org/",
@@ -429,13 +539,32 @@ describe JSON::LD::API do
429
539
  "ex:prop2": {"@id": "ex:Obj1"},
430
540
  "ex:null": ["foo"]
431
541
  }]
432
- }
433
- )
542
+ })
543
+ },
544
+ "default value for @type": {
545
+ frame: %({
546
+ "@context": {"ex": "http://example.org/"},
547
+ "@type": {"@default": "ex:Foo"},
548
+ "ex:foo": "bar"
549
+ }),
550
+ input: %({
551
+ "@context": {"ex": "http://example.org/"},
552
+ "@id": "ex:Sub1",
553
+ "ex:foo": "bar"
554
+ }),
555
+ output: %({
556
+ "@context": {"ex": "http://example.org/"},
557
+ "@graph": [{
558
+ "@id": "ex:Sub1",
559
+ "@type": "ex:Foo",
560
+ "ex:foo": "bar"
561
+ }]
562
+ })
434
563
  },
435
- "mixed content" => {
564
+ "mixed content": {
436
565
  frame: %({
437
566
  "@context": {"ex": "http://example.org/"},
438
- "ex:mixed": {"@embed": false}
567
+ "ex:mixed": {"@embed": "@never"}
439
568
  }),
440
569
  input: %({
441
570
  "@context": {"ex": "http://example.org/"},
@@ -456,10 +585,10 @@ describe JSON::LD::API do
456
585
  }]
457
586
  })
458
587
  },
459
- "no embedding (@embed: false)" => {
588
+ "no embedding (@embed: @never)": {
460
589
  frame: %({
461
590
  "@context": {"ex": "http://example.org/"},
462
- "ex:embed": {"@embed": false}
591
+ "ex:embed": {"@embed": "@never"}
463
592
  }),
464
593
  input: %({
465
594
  "@context": {"ex": "http://example.org/"},
@@ -477,7 +606,58 @@ describe JSON::LD::API do
477
606
  }]
478
607
  })
479
608
  },
480
- "mixed list" => {
609
+ "first embed (@embed: @once)": {
610
+ frame: %({
611
+ "@context": {"ex": "http://www.example.com/#"},
612
+ "@type": "ex:Thing",
613
+ "@embed": "@once"
614
+ }),
615
+ input: %({
616
+ "@context": {"ex": "http://www.example.com/#"},
617
+ "@id": "http://example/outer",
618
+ "@type": "ex:Thing",
619
+ "ex:embed1": {"@id": "http://example/embedded", "ex:name": "Embedded"},
620
+ "ex:embed2": {"@id": "http://example/embedded", "ex:name": "Embedded"}
621
+ }),
622
+ output: %({
623
+ "@context": {"ex": "http://www.example.com/#"},
624
+ "@graph": [
625
+ {
626
+ "@id": "http://example/outer",
627
+ "@type": "ex:Thing",
628
+ "ex:embed1": {"@id": "http://example/embedded", "ex:name": "Embedded"},
629
+ "ex:embed2": {"@id": "http://example/embedded"}
630
+ }
631
+ ]
632
+ }),
633
+ ordered: true
634
+ },
635
+ "always embed (@embed: @always)": {
636
+ frame: %({
637
+ "@context": {"ex": "http://www.example.com/#"},
638
+ "@type": "ex:Thing",
639
+ "@embed": "@always"
640
+ }),
641
+ input: %({
642
+ "@context": {"ex": "http://www.example.com/#"},
643
+ "@id": "http://example/outer",
644
+ "@type": "ex:Thing",
645
+ "ex:embed1": {"@id": "http://example/embedded", "ex:name": "Embedded"},
646
+ "ex:embed2": {"@id": "http://example/embedded", "ex:name": "Embedded"}
647
+ }),
648
+ output: %({
649
+ "@context": {"ex": "http://www.example.com/#"},
650
+ "@graph": [
651
+ {
652
+ "@id": "http://example/outer",
653
+ "@type": "ex:Thing",
654
+ "ex:embed1": {"@id": "http://example/embedded", "ex:name": "Embedded"},
655
+ "ex:embed2": {"@id": "http://example/embedded", "ex:name": "Embedded"}
656
+ }
657
+ ]
658
+ })
659
+ },
660
+ "mixed list": {
481
661
  frame: %({
482
662
  "@context": {"ex": "http://example.org/"},
483
663
  "ex:mixedlist": {}
@@ -507,7 +687,7 @@ describe JSON::LD::API do
507
687
  }]
508
688
  })
509
689
  },
510
- "framed list" => {
690
+ "framed list": {
511
691
  frame: %({
512
692
  "@context": {
513
693
  "ex": "http://example.org/",
@@ -542,7 +722,7 @@ describe JSON::LD::API do
542
722
  }]
543
723
  })
544
724
  },
545
- "presentation example" => {
725
+ "presentation example": {
546
726
  frame: %({
547
727
  "@context": {
548
728
  "primaryTopic": {
@@ -589,7 +769,7 @@ describe JSON::LD::API do
589
769
  }]
590
770
  })
591
771
  },
592
- "microdata manifest" => {
772
+ "microdata manifest": {
593
773
  frame: %({
594
774
  "@context": {
595
775
  "xsd": "http://www.w3.org/2001/XMLSchema#",
@@ -668,7 +848,7 @@ describe JSON::LD::API do
668
848
  }),
669
849
  processingMode: 'json-ld-1.1'
670
850
  },
671
- "library" => {
851
+ "library": {
672
852
  frame: %({
673
853
  "@context": {
674
854
  "dc": "http://purl.org/dc/elements/1.1/",
@@ -737,7 +917,7 @@ describe JSON::LD::API do
737
917
 
738
918
  describe "@reverse" do
739
919
  {
740
- "embed matched frames with @reverse" => {
920
+ "embed matched frames with @reverse": {
741
921
  frame: %({
742
922
  "@context": {"ex": "http://example.org/"},
743
923
  "@type": "ex:Type1",
@@ -770,7 +950,7 @@ describe JSON::LD::API do
770
950
  }]
771
951
  })
772
952
  },
773
- "embed matched frames with reversed property" => {
953
+ "embed matched frames with reversed property": {
774
954
  frame: %({
775
955
  "@context": {
776
956
  "ex": "http://example.org/",
@@ -807,25 +987,212 @@ describe JSON::LD::API do
807
987
  },
808
988
  }.each do |title, params|
809
989
  it title do
810
- begin
811
- input, frame, output = params[:input], params[:frame], params[:output]
812
- input = ::JSON.parse(input) if input.is_a?(String)
813
- frame = ::JSON.parse(frame) if frame.is_a?(String)
814
- output = ::JSON.parse(output) if output.is_a?(String)
815
- jld = JSON::LD::API.frame(input, frame, logger: logger)
816
- expect(jld).to produce_jsonld(output, logger)
817
- rescue JSON::LD::JsonLdError => e
818
- fail("#{e.class}: #{e.message}\n" +
819
- "#{logger}\n" +
820
- "Backtrace:\n#{e.backtrace.join("\n")}")
821
- end
990
+ do_frame(params)
822
991
  end
823
992
  end
824
993
  end
825
994
 
995
+ context "@included" do
996
+ {
997
+ "Basic Included array": {
998
+ input: %([{
999
+ "http://example.org/prop": [{"@value": "value"}],
1000
+ "http://example.org/foo": [{"@value": "bar"}]
1001
+ }, {
1002
+ "http://example.org/prop": [{"@value": "value2"}],
1003
+ "http://example.org/foo": [{"@value": "bar"}]
1004
+ }]),
1005
+ frame: %({
1006
+ "@context": {
1007
+ "@version": 1.1,
1008
+ "@vocab": "http://example.org/",
1009
+ "included": {"@id": "@included", "@container": "@set"}
1010
+ },
1011
+ "@requireAll": true,
1012
+ "foo": "bar",
1013
+ "prop": "value",
1014
+ "@included": [{
1015
+ "@requireAll": true,
1016
+ "foo": "bar",
1017
+ "prop": "value2"
1018
+ }]
1019
+ }),
1020
+ output: %({
1021
+ "@context": {
1022
+ "@version": 1.1,
1023
+ "@vocab": "http://example.org/",
1024
+ "included": {"@id": "@included", "@container": "@set"}
1025
+ },
1026
+ "foo": "bar",
1027
+ "included": [{
1028
+ "foo": "bar",
1029
+ "prop": "value2"
1030
+ }],
1031
+ "prop": "value"
1032
+ })
1033
+ },
1034
+ "Basic Included object": {
1035
+ input: %([{
1036
+ "http://example.org/prop": [{"@value": "value"}],
1037
+ "http://example.org/foo": [{"@value": "bar"}]
1038
+ }, {
1039
+ "http://example.org/prop": [{"@value": "value2"}],
1040
+ "http://example.org/foo": [{"@value": "bar"}]
1041
+ }]),
1042
+ frame: %({
1043
+ "@context": {
1044
+ "@version": 1.1,
1045
+ "@vocab": "http://example.org/"
1046
+ },
1047
+ "@requireAll": true,
1048
+ "foo": "bar",
1049
+ "prop": "value",
1050
+ "@included": [{
1051
+ "@requireAll": true,
1052
+ "foo": "bar",
1053
+ "prop": "value2"
1054
+ }]
1055
+ }),
1056
+ output: %({
1057
+ "@context": {
1058
+ "@version": 1.1,
1059
+ "@vocab": "http://example.org/"
1060
+ },
1061
+ "foo": "bar",
1062
+ "prop": "value",
1063
+ "@included": {
1064
+ "prop": "value2",
1065
+ "foo": "bar"
1066
+ }
1067
+ })
1068
+ },
1069
+ "json.api example": {
1070
+ input: %([{
1071
+ "@id": "http://example.org/base/1",
1072
+ "@type": ["http://example.org/vocab#articles"],
1073
+ "http://example.org/vocab#title": [{"@value": "JSON:API paints my bikeshed!"}],
1074
+ "http://example.org/vocab#self": [{"@id": "http://example.com/articles/1"}],
1075
+ "http://example.org/vocab#author": [{
1076
+ "@id": "http://example.org/base/9",
1077
+ "@type": ["http://example.org/vocab#people"],
1078
+ "http://example.org/vocab#self": [{"@id": "http://example.com/articles/1/relationships/author"}],
1079
+ "http://example.org/vocab#related": [{"@id": "http://example.com/articles/1/author"}]
1080
+ }],
1081
+ "http://example.org/vocab#comments": [{
1082
+ "http://example.org/vocab#self": [{"@id": "http://example.com/articles/1/relationships/comments"}],
1083
+ "http://example.org/vocab#related": [{"@id": "http://example.com/articles/1/comments"}]
1084
+ }],
1085
+ "@included": [{
1086
+ "@id": "http://example.org/base/9",
1087
+ "@type": ["http://example.org/vocab#people"],
1088
+ "http://example.org/vocab#first-name": [{"@value": "Dan"}],
1089
+ "http://example.org/vocab#last-name": [{"@value": "Gebhardt"}],
1090
+ "http://example.org/vocab#twitter": [{"@value": "dgeb"}],
1091
+ "http://example.org/vocab#self": [{"@id": "http://example.com/people/9"}]
1092
+ }, {
1093
+ "@id": "http://example.org/base/5",
1094
+ "@type": ["http://example.org/vocab#comments"],
1095
+ "http://example.org/vocab#body": [{"@value": "First!"}],
1096
+ "http://example.org/vocab#author": [{
1097
+ "@id": "http://example.org/base/2",
1098
+ "@type": ["http://example.org/vocab#people"]
1099
+ }],
1100
+ "http://example.org/vocab#self": [{"@id": "http://example.com/comments/5"}]
1101
+ }, {
1102
+ "@id": "http://example.org/base/12",
1103
+ "@type": ["http://example.org/vocab#comments"],
1104
+ "http://example.org/vocab#body": [{"@value": "I like XML better"}],
1105
+ "http://example.org/vocab#author": [{
1106
+ "@id": "http://example.org/base/9",
1107
+ "@type": ["http://example.org/vocab#people"]
1108
+ }],
1109
+ "http://example.org/vocab#self": [{"@id": "http://example.com/comments/12"}]
1110
+ }]
1111
+ }]),
1112
+ frame: %({
1113
+ "@context": {
1114
+ "@version": 1.1,
1115
+ "@vocab": "http://example.org/vocab#",
1116
+ "@base": "http://example.org/base/",
1117
+ "id": "@id",
1118
+ "type": "@type",
1119
+ "data": "@nest",
1120
+ "attributes": "@nest",
1121
+ "links": "@nest",
1122
+ "relationships": "@nest",
1123
+ "included": "@included",
1124
+ "author": {"@type": "@id"},
1125
+ "self": {"@type": "@id"},
1126
+ "related": {"@type": "@id"},
1127
+ "comments": {"@context": {"data": null}}
1128
+ },
1129
+ "data": {"type": "articles"},
1130
+ "included": {
1131
+ "@requireAll": true,
1132
+ "type": ["comments", "people"],
1133
+ "self": {}
1134
+ }
1135
+ }),
1136
+ output: %({
1137
+ "@context": {
1138
+ "@version": 1.1,
1139
+ "@vocab": "http://example.org/vocab#",
1140
+ "@base": "http://example.org/base/",
1141
+ "id": "@id",
1142
+ "type": "@type",
1143
+ "data": "@nest",
1144
+ "attributes": "@nest",
1145
+ "links": "@nest",
1146
+ "relationships": "@nest",
1147
+ "included": "@included",
1148
+ "author": {"@type": "@id"},
1149
+ "self": {"@type": "@id"},
1150
+ "related": {"@type": "@id"},
1151
+ "comments": {"@context": {"data": null}}
1152
+ },
1153
+ "id": "1",
1154
+ "type": "articles",
1155
+ "title": "JSON:API paints my bikeshed!",
1156
+ "self": "http://example.com/articles/1",
1157
+ "author": "9",
1158
+ "comments": {
1159
+ "self": "http://example.com/articles/1/relationships/comments",
1160
+ "related": "http://example.com/articles/1/comments"
1161
+ },
1162
+ "included": [{
1163
+ "id": "5",
1164
+ "type": "comments",
1165
+ "body": "First!",
1166
+ "author": {"id": "2", "type": "people"},
1167
+ "self": "http://example.com/comments/5"
1168
+ }, {
1169
+ "id": "9",
1170
+ "type": "people",
1171
+ "first-name": "Dan",
1172
+ "last-name": "Gebhardt",
1173
+ "twitter": "dgeb",
1174
+ "self": [
1175
+ "http://example.com/people/9",
1176
+ "http://example.com/articles/1/relationships/author"
1177
+ ],
1178
+ "related": "http://example.com/articles/1/author"
1179
+ }, {
1180
+ "id": "12",
1181
+ "type": "comments",
1182
+ "body": "I like XML better",
1183
+ "author": "9",
1184
+ "self": "http://example.com/comments/12"
1185
+ }]
1186
+ }),
1187
+ },
1188
+ }.each do |title, params|
1189
+ it(title) {do_frame(params.merge(processingMode: 'json-ld-1.1'))}
1190
+ end
1191
+ end
1192
+
826
1193
  describe "node pattern" do
827
1194
  {
828
- "matches a deep node pattern" => {
1195
+ "matches a deep node pattern": {
829
1196
  frame: %({
830
1197
  "@context": {"ex": "http://example.org/"},
831
1198
  "ex:p": {
@@ -874,10 +1241,9 @@ describe JSON::LD::API do
874
1241
 
875
1242
  describe "value pattern" do
876
1243
  {
877
- "matches exact values" => {
1244
+ "matches exact values": {
878
1245
  frame: %({
879
1246
  "@context": {"ex": "http://example.org/"},
880
- "@id": "ex:Sub1",
881
1247
  "ex:p": "P",
882
1248
  "ex:q": {"@value": "Q", "@type": "ex:q"},
883
1249
  "ex:r": {"@value": "R", "@language": "r"}
@@ -899,10 +1265,9 @@ describe JSON::LD::API do
899
1265
  }]
900
1266
  })
901
1267
  },
902
- "matches wildcard @value" => {
1268
+ "matches wildcard @value": {
903
1269
  frame: %({
904
1270
  "@context": {"ex": "http://example.org/"},
905
- "@id": "ex:Sub1",
906
1271
  "ex:p": {"@value": {}},
907
1272
  "ex:q": {"@value": {}, "@type": "ex:q"},
908
1273
  "ex:r": {"@value": {}, "@language": "r"}
@@ -924,10 +1289,9 @@ describe JSON::LD::API do
924
1289
  }]
925
1290
  })
926
1291
  },
927
- "matches wildcard @type" => {
1292
+ "matches wildcard @type": {
928
1293
  frame: %({
929
1294
  "@context": {"ex": "http://example.org/"},
930
- "@id": "ex:Sub1",
931
1295
  "ex:q": {"@value": "Q", "@type": {}}
932
1296
  }),
933
1297
  input: %({
@@ -943,10 +1307,9 @@ describe JSON::LD::API do
943
1307
  }]
944
1308
  })
945
1309
  },
946
- "matches wildcard @language" => {
1310
+ "matches wildcard @language": {
947
1311
  frame: %({
948
1312
  "@context": {"ex": "http://example.org/"},
949
- "@id": "ex:Sub1",
950
1313
  "ex:r": {"@value": "R", "@language": {}}
951
1314
  }),
952
1315
  input: %({
@@ -962,10 +1325,9 @@ describe JSON::LD::API do
962
1325
  }]
963
1326
  })
964
1327
  },
965
- "match none @type" => {
1328
+ "match none @type": {
966
1329
  frame: %({
967
1330
  "@context": {"ex": "http://example.org/"},
968
- "@id": "ex:Sub1",
969
1331
  "ex:p": {"@value": {}, "@type": []},
970
1332
  "ex:q": {"@value": {}, "@type": "ex:q"},
971
1333
  "ex:r": {"@value": {}, "@language": "r"}
@@ -987,10 +1349,9 @@ describe JSON::LD::API do
987
1349
  }]
988
1350
  })
989
1351
  },
990
- "match none @language" => {
1352
+ "match none @language": {
991
1353
  frame: %({
992
1354
  "@context": {"ex": "http://example.org/"},
993
- "@id": "ex:Sub1",
994
1355
  "ex:p": {"@value": {}, "@language": []},
995
1356
  "ex:q": {"@value": {}, "@type": "ex:q"},
996
1357
  "ex:r": {"@value": {}, "@language": "r"}
@@ -1012,10 +1373,9 @@ describe JSON::LD::API do
1012
1373
  }]
1013
1374
  })
1014
1375
  },
1015
- "matches some @value" => {
1376
+ "matches some @value": {
1016
1377
  frame: %({
1017
1378
  "@context": {"ex": "http://example.org/"},
1018
- "@id": "ex:Sub1",
1019
1379
  "ex:p": {"@value": ["P", "Q", "R"]},
1020
1380
  "ex:q": {"@value": ["P", "Q", "R"], "@type": "ex:q"},
1021
1381
  "ex:r": {"@value": ["P", "Q", "R"], "@language": "r"}
@@ -1037,10 +1397,9 @@ describe JSON::LD::API do
1037
1397
  }]
1038
1398
  })
1039
1399
  },
1040
- "matches some @type" => {
1400
+ "matches some @type": {
1041
1401
  frame: %({
1042
1402
  "@context": {"ex": "http://example.org/"},
1043
- "@id": "ex:Sub1",
1044
1403
  "ex:q": {"@value": "Q", "@type": ["ex:q", "ex:Q"]}
1045
1404
  }),
1046
1405
  input: %({
@@ -1056,29 +1415,27 @@ describe JSON::LD::API do
1056
1415
  }]
1057
1416
  })
1058
1417
  },
1059
- "matches some @language" => {
1418
+ "matches some @language": {
1060
1419
  frame: %({
1061
1420
  "@context": {"ex": "http://example.org/"},
1062
- "@id": "ex:Sub1",
1063
1421
  "ex:r": {"@value": "R", "@language": ["p", "q", "r"]}
1064
1422
  }),
1065
1423
  input: %({
1066
1424
  "@context": {"ex": "http://example.org/"},
1067
1425
  "@id": "ex:Sub1",
1068
- "ex:r": {"@value": "R", "@language": "r"}
1426
+ "ex:r": {"@value": "R", "@language": "R"}
1069
1427
  }),
1070
1428
  output: %({
1071
1429
  "@context": {"ex": "http://example.org/"},
1072
1430
  "@graph": [{
1073
1431
  "@id": "ex:Sub1",
1074
- "ex:r": {"@value": "R", "@language": "r"}
1432
+ "ex:r": {"@value": "R", "@language": "R"}
1075
1433
  }]
1076
1434
  })
1077
1435
  },
1078
- "excludes non-matched values" => {
1436
+ "excludes non-matched values": {
1079
1437
  frame: %({
1080
1438
  "@context": {"ex": "http://example.org/"},
1081
- "@id": "ex:Sub1",
1082
1439
  "ex:p": {"@value": {}},
1083
1440
  "ex:q": {"@value": {}, "@type": "ex:q"},
1084
1441
  "ex:r": {"@value": {}, "@language": "R"}
@@ -1096,7 +1453,7 @@ describe JSON::LD::API do
1096
1453
  "@id": "ex:Sub1",
1097
1454
  "ex:p": "P",
1098
1455
  "ex:q": {"@value": "Q", "@type": "ex:q"},
1099
- "ex:r": {"@value": "R", "@language": "r"}
1456
+ "ex:r": {"@value": "R", "@language": "R"}
1100
1457
  }]
1101
1458
  })
1102
1459
  },
@@ -1109,7 +1466,7 @@ describe JSON::LD::API do
1109
1466
 
1110
1467
  describe "named graphs" do
1111
1468
  {
1112
- "Merge graphs if no outer @graph is used" => {
1469
+ "Merge graphs if no outer @graph is used": {
1113
1470
  frame: %({
1114
1471
  "@context": {"@vocab": "urn:"},
1115
1472
  "@type": "Class"
@@ -1133,7 +1490,7 @@ describe JSON::LD::API do
1133
1490
  }),
1134
1491
  processingMode: 'json-ld-1.1'
1135
1492
  },
1136
- "Frame default graph if outer @graph is used" => {
1493
+ "Frame default graph if outer @graph is used": {
1137
1494
  frame: %({
1138
1495
  "@context": {"@vocab": "urn:"},
1139
1496
  "@type": "Class",
@@ -1165,7 +1522,7 @@ describe JSON::LD::API do
1165
1522
  }),
1166
1523
  processingMode: 'json-ld-1.1'
1167
1524
  },
1168
- "Merge one graph and preserve another" => {
1525
+ "Merge one graph and preserve another": {
1169
1526
  frame: %({
1170
1527
  "@context": {"@vocab": "urn:"},
1171
1528
  "@type": "Class",
@@ -1210,7 +1567,7 @@ describe JSON::LD::API do
1210
1567
  }),
1211
1568
  processingMode: 'json-ld-1.1'
1212
1569
  },
1213
- "Merge one graph and deep preserve another" => {
1570
+ "Merge one graph and deep preserve another": {
1214
1571
  frame: %({
1215
1572
  "@context": {"@vocab": "urn:"},
1216
1573
  "@type": "Class",
@@ -1259,7 +1616,7 @@ describe JSON::LD::API do
1259
1616
  }),
1260
1617
  processingMode: 'json-ld-1.1'
1261
1618
  },
1262
- "library" => {
1619
+ "library": {
1263
1620
  frame: %({
1264
1621
  "@context": {"@vocab": "http://example.org/"},
1265
1622
  "@type": "Library",
@@ -1311,7 +1668,65 @@ describe JSON::LD::API do
1311
1668
  }
1312
1669
  }),
1313
1670
  processingMode: 'json-ld-1.1'
1314
- }
1671
+ },
1672
+ "named graph with @embed: @never": {
1673
+ input: %({
1674
+ "@id": "ex:cred",
1675
+ "ex:subject": {
1676
+ "@id": "ex:Subject",
1677
+ "ex:name": "the subject"
1678
+ },
1679
+ "ex:proof": {
1680
+ "@graph": {
1681
+ "@type": "ex:Proof",
1682
+ "ex:name": "the proof",
1683
+ "ex:signer": [{
1684
+ "@id": "ex:Subject",
1685
+ "ex:name": "something different"
1686
+ }]
1687
+ }
1688
+ }
1689
+ }),
1690
+ frame: %({
1691
+ "@context": {
1692
+ "@version": 1.1,
1693
+ "proof": {"@id": "ex:proof", "@container": "@graph"}
1694
+ },
1695
+ "@graph": {
1696
+ "proof": {"@embed": "@never"}
1697
+ }
1698
+ }),
1699
+ output: %({
1700
+ "@context": {
1701
+ "@version": 1.1,
1702
+ "proof": {
1703
+ "@id": "ex:proof",
1704
+ "@container": "@graph"
1705
+ }
1706
+ },
1707
+ "@id": "ex:cred",
1708
+ "ex:subject": {
1709
+ "@id": "ex:Subject",
1710
+ "ex:name": "the subject"
1711
+ },
1712
+ "proof": {
1713
+ "@included": [
1714
+ {
1715
+ "@type": "ex:Proof",
1716
+ "ex:name": "the proof",
1717
+ "ex:signer": {
1718
+ "@id": "ex:Subject"
1719
+ }
1720
+ },
1721
+ {
1722
+ "@id": "ex:Subject",
1723
+ "ex:name": "something different"
1724
+ }
1725
+ ]
1726
+ }
1727
+ }),
1728
+ processingMode: 'json-ld-1.1'
1729
+ },
1315
1730
  }.each do |title, params|
1316
1731
  it title do
1317
1732
  do_frame(params)
@@ -1321,11 +1736,11 @@ describe JSON::LD::API do
1321
1736
  end
1322
1737
 
1323
1738
  describe "prune blank nodes" do
1324
- it "preserves single-use bnode identifiers if @version 1.0" do
1325
- do_frame(
1326
- input: %({
1739
+ {
1740
+ "preserves single-use bnode identifiers if @version 1.0": {
1741
+ frame: %({
1327
1742
  "@context": {
1328
- "dc0": "http://purl.org/dc/terms/",
1743
+ "dc": "http://purl.org/dc/terms/",
1329
1744
  "dc:creator": {
1330
1745
  "@type": "@id"
1331
1746
  },
@@ -1334,11 +1749,9 @@ describe JSON::LD::API do
1334
1749
  },
1335
1750
  "@id": "http://example.com/asset",
1336
1751
  "@type": "ps:Asset",
1337
- "dc:creator": {
1338
- "foaf:name": "John Doe"
1339
- }
1752
+ "dc:creator": {}
1340
1753
  }),
1341
- frame: %({
1754
+ input: %({
1342
1755
  "@context": {
1343
1756
  "dc": "http://purl.org/dc/terms/",
1344
1757
  "dc:creator": {
@@ -1349,7 +1762,9 @@ describe JSON::LD::API do
1349
1762
  },
1350
1763
  "@id": "http://example.com/asset",
1351
1764
  "@type": "ps:Asset",
1352
- "dc:creator": {}
1765
+ "dc:creator": {
1766
+ "foaf:name": "John Doe"
1767
+ }
1353
1768
  }),
1354
1769
  output: %({
1355
1770
  "@context": {
@@ -1370,316 +1785,531 @@ describe JSON::LD::API do
1370
1785
  }
1371
1786
  }
1372
1787
  ]
1373
- })
1374
- )
1375
- end
1376
- end
1377
-
1378
- context "problem cases" do
1379
- it "pr #20" do
1380
- expanded = %([
1381
- {
1382
- "@id": "_:gregg",
1383
- "@type": "http://xmlns.com/foaf/0.1/Person",
1384
- "http://xmlns.com/foaf/0.1/name": "Gregg Kellogg"
1385
- }, {
1386
- "@id": "http://manu.sporny.org/#me",
1387
- "@type": "http://xmlns.com/foaf/0.1/Person",
1388
- "http://xmlns.com/foaf/0.1/knows": {"@id": "_:gregg"},
1389
- "http://xmlns.com/foaf/0.1/name": "Manu Sporny"
1390
- }
1391
- ])
1392
- expected = %({
1393
- "@graph": [
1394
- {
1395
- "@id": "_:b0",
1396
- "@type": "http://xmlns.com/foaf/0.1/Person",
1397
- "http://xmlns.com/foaf/0.1/name": "Gregg Kellogg"
1398
- },
1399
- {
1400
- "@id": "http://manu.sporny.org/#me",
1401
- "@type": "http://xmlns.com/foaf/0.1/Person",
1402
- "http://xmlns.com/foaf/0.1/knows": {
1403
- "@id": "_:b0",
1404
- "@type": "http://xmlns.com/foaf/0.1/Person",
1405
- "http://xmlns.com/foaf/0.1/name": "Gregg Kellogg"
1788
+ }),
1789
+ processingMode: 'json-ld-1.0'
1790
+ },
1791
+ "preserves single-use bnode identifiers if pruneBlankNodeIdentifiers=false": {
1792
+ frame: %({
1793
+ "@context": {
1794
+ "dc": "http://purl.org/dc/terms/",
1795
+ "dc:creator": {
1796
+ "@type": "@id"
1406
1797
  },
1407
- "http://xmlns.com/foaf/0.1/name": "Manu Sporny"
1408
- }
1409
- ]
1410
- })
1411
- do_frame(input: expanded, frame: {}, output: expected)
1412
- end
1413
-
1414
- it "issue #28" do
1415
- input = %({
1416
- "@context": {
1417
- "rdfs": "http://www.w3.org/2000/01/rdf-schema#"
1418
- },
1419
- "@id": "http://www.myresource/uuid",
1420
- "http://www.myresource.com/ontology/1.0#talksAbout": [
1421
- {
1422
- "@id": "http://rdf.freebase.com/ns/m.018w8",
1423
- "rdfs:label": [
1424
- {
1425
- "@value": "Basketball",
1426
- "@language": "en"
1427
- }
1428
- ]
1429
- }
1430
- ]
1431
- })
1432
- frame = %({
1433
- "@context": {
1434
- "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
1435
- "talksAbout": {
1436
- "@id": "http://www.myresource.com/ontology/1.0#talksAbout",
1437
- "@type": "@id"
1798
+ "foaf": "http://xmlns.com/foaf/0.1/",
1799
+ "ps": "http://purl.org/payswarm#"
1438
1800
  },
1439
- "label": {
1440
- "@id": "rdfs:label",
1441
- "@language": "en"
1442
- }
1443
- },
1444
- "@id": "http://www.myresource/uuid"
1445
- })
1446
- expected = %({
1447
- "@context": {
1448
- "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
1449
- "talksAbout": {
1450
- "@id": "http://www.myresource.com/ontology/1.0#talksAbout",
1451
- "@type": "@id"
1801
+ "@id": "http://example.com/asset",
1802
+ "@type": "ps:Asset",
1803
+ "dc:creator": {}
1804
+ }),
1805
+ input: %({
1806
+ "@context": {
1807
+ "dc": "http://purl.org/dc/terms/",
1808
+ "dc:creator": {
1809
+ "@type": "@id"
1810
+ },
1811
+ "foaf": "http://xmlns.com/foaf/0.1/",
1812
+ "ps": "http://purl.org/payswarm#"
1452
1813
  },
1453
- "label": {
1454
- "@id": "rdfs:label",
1455
- "@language": "en"
1814
+ "@id": "http://example.com/asset",
1815
+ "@type": "ps:Asset",
1816
+ "dc:creator": {
1817
+ "foaf:name": "John Doe"
1456
1818
  }
1457
- },
1458
- "@graph": [
1459
- {
1460
- "@id": "http://www.myresource/uuid",
1461
- "talksAbout": {
1462
- "@id": "http://rdf.freebase.com/ns/m.018w8",
1463
- "label": "Basketball"
1819
+ }),
1820
+ output: %({
1821
+ "@context": {
1822
+ "dc": "http://purl.org/dc/terms/",
1823
+ "dc:creator": {
1824
+ "@type": "@id"
1825
+ },
1826
+ "foaf": "http://xmlns.com/foaf/0.1/",
1827
+ "ps": "http://purl.org/payswarm#"
1828
+ },
1829
+ "@graph": [
1830
+ {
1831
+ "@id": "http://example.com/asset",
1832
+ "@type": "ps:Asset",
1833
+ "dc:creator": {
1834
+ "@id": "_:b0",
1835
+ "foaf:name": "John Doe"
1836
+ }
1464
1837
  }
1465
- }
1466
- ]
1467
- })
1468
- do_frame(input: input, frame: frame, output: expected)
1469
- end
1470
-
1471
- it "framing with @version: 1.1 prunes identifiers" do
1472
- input = %({
1473
- "@context": {
1474
- "@version": 1.1,
1475
- "@vocab": "https://example.com#",
1476
- "ex": "http://example.org/",
1477
- "claim": {
1478
- "@id": "ex:claim",
1479
- "@container": "@graph"
1838
+ ]
1839
+ }),
1840
+ pruneBlankNodeIdentiers: false
1841
+ },
1842
+ "framing with @version: 1.1 prunes identifiers": {
1843
+ frame: %({
1844
+ "@context": {
1845
+ "@version": 1.1,
1846
+ "@vocab": "https://example.com#",
1847
+ "ex": "http://example.org/",
1848
+ "claim": {
1849
+ "@id": "ex:claim",
1850
+ "@container": "@graph"
1851
+ },
1852
+ "id": "@id"
1480
1853
  },
1481
- "id": "@id"
1482
- },
1483
- "claim": {
1484
- "id": "ex:1",
1485
- "test": "foo"
1486
- }
1487
- })
1488
- frame = %({
1489
- "@context": {
1490
- "@version": 1.1,
1491
- "@vocab": "https://example.com#",
1492
- "ex": "http://example.org/",
1493
- "claim": {
1494
- "@id": "ex:claim",
1495
- "@container": "@graph"
1854
+ "claim": {}
1855
+ }),
1856
+ input: %({
1857
+ "@context": {
1858
+ "@version": 1.1,
1859
+ "@vocab": "https://example.com#",
1860
+ "ex": "http://example.org/",
1861
+ "claim": {
1862
+ "@id": "ex:claim",
1863
+ "@container": "@graph"
1864
+ },
1865
+ "id": "@id"
1496
1866
  },
1497
- "id": "@id"
1498
- },
1499
- "claim": {}
1500
- })
1501
- expected = %({
1502
- "@context": {
1503
- "@version": 1.1,
1504
- "@vocab": "https://example.com#",
1505
- "ex": "http://example.org/",
1506
1867
  "claim": {
1507
- "@id": "ex:claim",
1508
- "@container": "@graph"
1868
+ "id": "ex:1",
1869
+ "test": "foo"
1870
+ }
1871
+ }),
1872
+ output: %({
1873
+ "@context": {
1874
+ "@version": 1.1,
1875
+ "@vocab": "https://example.com#",
1876
+ "ex": "http://example.org/",
1877
+ "claim": {
1878
+ "@id": "ex:claim",
1879
+ "@container": "@graph"
1880
+ },
1881
+ "id": "@id"
1509
1882
  },
1510
- "id": "@id"
1511
- },
1512
- "claim": {
1513
- "id": "ex:1",
1514
- "test": "foo"
1515
- }
1516
- })
1517
- do_frame(input: input, frame: frame, output: expected, processingMode: 'json-ld-1.1')
1883
+ "claim": {
1884
+ "id": "ex:1",
1885
+ "test": "foo"
1886
+ }
1887
+ }),
1888
+ processingMode: 'json-ld-1.1'
1889
+ }
1890
+ }.each do |title, params|
1891
+ it title do
1892
+ do_frame(params)
1893
+ end
1518
1894
  end
1895
+ end
1519
1896
 
1520
- it "PR #663" do
1521
- input = %({
1522
- "@context": {
1523
- "@vocab": "http://example.com/",
1524
- "loves": {
1525
- "@type": "@id"
1897
+ context "problem cases" do
1898
+ {
1899
+ "pr #20": {
1900
+ frame: %({}),
1901
+ input: %([
1902
+ {
1903
+ "@id": "_:gregg",
1904
+ "@type": "http://xmlns.com/foaf/0.1/Person",
1905
+ "http://xmlns.com/foaf/0.1/name": "Gregg Kellogg"
1906
+ }, {
1907
+ "@id": "http://manu.sporny.org/#me",
1908
+ "@type": "http://xmlns.com/foaf/0.1/Person",
1909
+ "http://xmlns.com/foaf/0.1/knows": {"@id": "_:gregg"},
1910
+ "http://xmlns.com/foaf/0.1/name": "Manu Sporny"
1911
+ }
1912
+ ]),
1913
+ output: %({
1914
+ "@graph": [
1915
+ {
1916
+ "@id": "_:b0",
1917
+ "@type": "http://xmlns.com/foaf/0.1/Person",
1918
+ "http://xmlns.com/foaf/0.1/name": "Gregg Kellogg"
1919
+ },
1920
+ {
1921
+ "@id": "http://manu.sporny.org/#me",
1922
+ "@type": "http://xmlns.com/foaf/0.1/Person",
1923
+ "http://xmlns.com/foaf/0.1/knows": {
1924
+ "@id": "_:b0",
1925
+ "@type": "http://xmlns.com/foaf/0.1/Person",
1926
+ "http://xmlns.com/foaf/0.1/name": "Gregg Kellogg"
1927
+ },
1928
+ "http://xmlns.com/foaf/0.1/name": "Manu Sporny"
1929
+ }
1930
+ ]
1931
+ })
1932
+ },
1933
+ "issue #28": {
1934
+ frame: %({
1935
+ "@context": {
1936
+ "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
1937
+ "talksAbout": {
1938
+ "@id": "http://www.myresource.com/ontology/1.0#talksAbout",
1939
+ "@type": "@id"
1940
+ },
1941
+ "label": {
1942
+ "@id": "rdfs:label",
1943
+ "@language": "en"
1944
+ }
1526
1945
  },
1527
- "unionOf": {
1528
- "@type": "@id",
1529
- "@id": "owl:unionOf",
1530
- "@container": "@list"
1946
+ "@id": "http://www.myresource/uuid"
1947
+ }),
1948
+ input: %({
1949
+ "@context": {
1950
+ "rdfs": "http://www.w3.org/2000/01/rdf-schema#"
1531
1951
  },
1532
- "Class": "owl:Class"
1533
- },
1534
- "@graph": [
1535
- {
1952
+ "@id": "http://www.myresource/uuid",
1953
+ "http://www.myresource.com/ontology/1.0#talksAbout": [
1954
+ {
1955
+ "@id": "http://rdf.freebase.com/ns/m.018w8",
1956
+ "rdfs:label": [
1957
+ {
1958
+ "@value": "Basketball",
1959
+ "@language": "en"
1960
+ }
1961
+ ]
1962
+ }
1963
+ ]
1964
+ }),
1965
+ output: %({
1966
+ "@context": {
1967
+ "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
1968
+ "talksAbout": {
1969
+ "@id": "http://www.myresource.com/ontology/1.0#talksAbout",
1970
+ "@type": "@id"
1971
+ },
1972
+ "label": {
1973
+ "@id": "rdfs:label",
1974
+ "@language": "en"
1975
+ }
1976
+ },
1977
+ "@graph": [
1978
+ {
1979
+ "@id": "http://www.myresource/uuid",
1980
+ "talksAbout": {
1981
+ "@id": "http://rdf.freebase.com/ns/m.018w8",
1982
+ "label": "Basketball"
1983
+ }
1984
+ }
1985
+ ]
1986
+ })
1987
+ },
1988
+ "PR #663 - Multiple named graphs": {
1989
+ frame: %({
1990
+ "@context": {
1991
+ "@vocab": "http://example.com/",
1992
+ "loves": {"@type": "@id"},
1993
+ "unionOf": {
1994
+ "@type": "@id",
1995
+ "@id": "owl:unionOf",
1996
+ "@container": "@list"
1997
+ },
1998
+ "Class": "owl:Class"
1999
+ },
2000
+ "@graph": [
2001
+ {
2002
+ "@explicit": false,
2003
+ "@embed": "@once",
2004
+ "@type": ["Act", "Class"],
2005
+ "@graph": [{
2006
+ "@explicit": true,
2007
+ "@embed": "@always",
2008
+ "@type": "Person",
2009
+ "@id": {},
2010
+ "loves": {"@embed": "@never"}
2011
+ }]
2012
+ }
2013
+ ]
2014
+ }),
2015
+ input: %({
2016
+ "@context": {
2017
+ "@vocab": "http://example.com/",
2018
+ "loves": {"@type": "@id"},
2019
+ "unionOf": {
2020
+ "@type": "@id",
2021
+ "@id": "owl:unionOf",
2022
+ "@container": "@list"
2023
+ },
2024
+ "Class": "owl:Class"
2025
+ },
2026
+ "@graph": [{
1536
2027
  "@type": "Act",
1537
2028
  "@graph": [
1538
- {
1539
- "@id": "Romeo",
1540
- "@type": "Person"
1541
- },
1542
- {
1543
- "@id": "Juliet",
1544
- "@type": "Person"
1545
- }
2029
+ {"@id": "Romeo", "@type": "Person"},
2030
+ {"@id": "Juliet", "@type": "Person"}
1546
2031
  ]
1547
- },
1548
- {
2032
+ }, {
1549
2033
  "@id": "ActTwo",
1550
2034
  "@type": "Act",
1551
2035
  "@graph": [
1552
- {
1553
- "@id": "Romeo",
1554
- "@type": "Person",
1555
- "loves": "Juliet"
1556
- },
1557
- {
1558
- "@id": "Juliet",
1559
- "@type": "Person",
1560
- "loves": "Romeo"
1561
- }
2036
+ {"@id": "Romeo", "@type": "Person", "loves": "Juliet"},
2037
+ {"@id": "Juliet", "@type": "Person", "loves": "Romeo"}
1562
2038
  ]
1563
- },
1564
- {
2039
+ }, {
1565
2040
  "@id": "Person",
1566
2041
  "@type": "Class",
1567
2042
  "unionOf": {
1568
2043
  "@list": [
1569
- {
1570
- "@id": "Montague",
1571
- "@type": "Class"
1572
- },
1573
- {
1574
- "@id": "Capulet",
1575
- "@type": "Class"
1576
- }
2044
+ {"@id": "Montague", "@type": "Class"},
2045
+ {"@id": "Capulet", "@type": "Class"}
1577
2046
  ]
1578
2047
  }
1579
- }
1580
- ]
1581
- })
1582
- frame = %({
1583
- "@context": {
1584
- "@vocab": "http://example.com/",
1585
- "loves": {
1586
- "@type": "@id"
1587
- },
1588
- "unionOf": {
1589
- "@type": "@id",
1590
- "@id": "owl:unionOf",
1591
- "@container": "@list"
1592
- },
1593
- "Class": "owl:Class"
1594
- },
1595
- "@graph": [
1596
- {
1597
- "@explicit": false,
1598
- "@embed": "@last",
1599
- "@type": [
1600
- "Act",
1601
- "Class"
1602
- ],
1603
- "@graph": [{
1604
- "@explicit": true,
1605
- "@embed": "@always",
1606
- "@type": "Person",
1607
- "@id": {},
1608
- "loves": {"@embed": "@never"}
1609
- }]
1610
- }
1611
- ]
1612
- })
1613
- expected = %({
1614
- "@context": {
1615
- "@vocab": "http://example.com/",
1616
- "loves": {
1617
- "@type": "@id"
1618
- },
1619
- "unionOf": {
1620
- "@type": "@id",
1621
- "@id": "owl:unionOf",
1622
- "@container": "@list"
2048
+ }]
2049
+ }),
2050
+ output: %({
2051
+ "@context": {
2052
+ "@vocab": "http://example.com/",
2053
+ "loves": {"@type": "@id"},
2054
+ "unionOf": {
2055
+ "@type": "@id",
2056
+ "@id": "owl:unionOf",
2057
+ "@container": "@list"
2058
+ },
2059
+ "Class": "owl:Class"
1623
2060
  },
1624
- "Class": "owl:Class"
1625
- },
1626
- "@graph": [
1627
- {
1628
- "@graph": [
1629
- {
1630
- "@id": "Juliet",
1631
- "@type": "Person",
1632
- "loves": "Romeo"
1633
- },
1634
- {
1635
- "@id": "Romeo",
1636
- "@type": "Person",
1637
- "loves": "Juliet"
1638
- }
1639
- ],
2061
+ "@graph": [{
1640
2062
  "@id": "ActTwo",
1641
- "@type": "Act"
1642
- },
1643
- {
2063
+ "@type": "Act",
2064
+ "@graph": [
2065
+ {"@id": "Juliet", "@type": "Person", "loves": "Romeo"},
2066
+ {"@id": "Romeo", "@type": "Person", "loves": "Juliet"}
2067
+ ]
2068
+ }, {
1644
2069
  "@id": "Capulet",
1645
2070
  "@type": "Class"
1646
- },
1647
- {
2071
+ }, {
1648
2072
  "@id": "Montague",
1649
2073
  "@type": "Class"
1650
- },
1651
- {
2074
+ }, {
1652
2075
  "@id": "Person",
1653
2076
  "@type": "Class",
1654
2077
  "unionOf": [
1655
- {
1656
- "@id": "Montague",
1657
- "@type": "Class"
1658
- },
1659
- {
1660
- "@id": "Capulet",
1661
- "@type": "Class"
1662
- }
2078
+ {"@id": "Montague", "@type": "Class"},
2079
+ {"@id": "Capulet", "@type": "Class"}
1663
2080
  ]
1664
- },
1665
- {
2081
+ }, {
2082
+ "@type": "Act",
1666
2083
  "@graph": [
1667
2084
  {
1668
2085
  "@id": "Juliet",
1669
2086
  "@type": "Person",
1670
2087
  "loves": null
1671
- },
1672
- {
2088
+ }, {
1673
2089
  "@id": "Romeo",
1674
2090
  "@type": "Person",
1675
2091
  "loves": null
1676
2092
  }
1677
- ],
1678
- "@type": "Act"
2093
+ ]
2094
+ }]
2095
+ }),
2096
+ processingMode: 'json-ld-1.1'
2097
+ },
2098
+ "w3c/json-ld-framing#5": {
2099
+ frame: %({
2100
+ "@context" : {
2101
+ "@vocab" : "http://purl.bdrc.io/ontology/core/",
2102
+ "taxSubclassOf" : {
2103
+ "@id" : "http://purl.bdrc.io/ontology/core/taxSubclassOf",
2104
+ "@type" : "@id"
2105
+ },
2106
+ "bdr" : "http://purl.bdrc.io/resource/",
2107
+ "children": { "@reverse": "http://purl.bdrc.io/ontology/core/taxSubclassOf" }
2108
+ },
2109
+ "@id" : "bdr:O9TAXTBRC201605",
2110
+ "children": {
2111
+ "children": {
2112
+ "children": {}
2113
+ }
2114
+ }
2115
+ }),
2116
+ input: %({
2117
+ "@context": {
2118
+ "@vocab": "http://purl.bdrc.io/ontology/core/",
2119
+ "taxSubclassOf": {
2120
+ "@id": "http://purl.bdrc.io/ontology/core/taxSubclassOf",
2121
+ "@type": "@id"
2122
+ },
2123
+ "bdr": "http://purl.bdrc.io/resource/"
2124
+ },
2125
+ "@graph": [{
2126
+ "@id": "bdr:O9TAXTBRC201605",
2127
+ "@type": "Taxonomy"
2128
+ }, {
2129
+ "@id": "bdr:O9TAXTBRC201605_0001",
2130
+ "@type": "Taxonomy",
2131
+ "taxSubclassOf": "bdr:O9TAXTBRC201605"
2132
+ }, {
2133
+ "@id": "bdr:O9TAXTBRC201605_0002",
2134
+ "@type": "Taxonomy",
2135
+ "taxSubclassOf": "bdr:O9TAXTBRC201605_0001"
2136
+ }, {
2137
+ "@id": "bdr:O9TAXTBRC201605_0010",
2138
+ "@type": "Taxonomy",
2139
+ "taxSubclassOf": "bdr:O9TAXTBRC201605"
2140
+ }]
2141
+ }),
2142
+ output: %({
2143
+ "@context" : {
2144
+ "@vocab" : "http://purl.bdrc.io/ontology/core/",
2145
+ "taxSubclassOf" : {
2146
+ "@id" : "http://purl.bdrc.io/ontology/core/taxSubclassOf",
2147
+ "@type" : "@id"
2148
+ },
2149
+ "bdr" : "http://purl.bdrc.io/resource/",
2150
+ "children": { "@reverse": "http://purl.bdrc.io/ontology/core/taxSubclassOf" }
2151
+ },
2152
+ "@id" : "bdr:O9TAXTBRC201605",
2153
+ "@type": "Taxonomy",
2154
+ "children": [{
2155
+ "@id": "bdr:O9TAXTBRC201605_0001",
2156
+ "@type": "Taxonomy",
2157
+ "taxSubclassOf": "bdr:O9TAXTBRC201605",
2158
+ "children": {
2159
+ "@id": "bdr:O9TAXTBRC201605_0002",
2160
+ "@type": "Taxonomy",
2161
+ "taxSubclassOf": "bdr:O9TAXTBRC201605_0001"
2162
+ }
2163
+ }, {
2164
+ "@id": "bdr:O9TAXTBRC201605_0010",
2165
+ "@type": "Taxonomy",
2166
+ "taxSubclassOf": "bdr:O9TAXTBRC201605"
2167
+ }]
2168
+ }),
2169
+ processingMode: 'json-ld-1.1'
2170
+ },
2171
+ "issue json-ld-framing#30": {
2172
+ input: %({
2173
+ "@context": {"eg": "https://example.org/ns/"},
2174
+ "@id": "https://example.org/what",
2175
+ "eg:sameAs": "https://example.org/what",
2176
+ "eg:age": 42
2177
+ }),
2178
+ frame: %({
2179
+ "@context": {"eg": "https://example.org/ns/"},
2180
+ "@id": "https://example.org/what"
2181
+ }),
2182
+ output: %({
2183
+ "@context": {"eg": "https://example.org/ns/"},
2184
+ "@graph": [{
2185
+ "@id": "https://example.org/what",
2186
+ "eg:age": 42,
2187
+ "eg:sameAs": "https://example.org/what"
2188
+ }]
2189
+ })
2190
+ },
2191
+ "issue json-ld-framing#64": {
2192
+ input: %({
2193
+ "@context": {
2194
+ "@version": 1.1,
2195
+ "@vocab": "http://example.org/vocab#"
2196
+ },
2197
+ "@id": "http://example.org/1",
2198
+ "@type": "HumanMadeObject",
2199
+ "produced_by": {
2200
+ "@type": "Production",
2201
+ "_label": "Top Production",
2202
+ "part": {
2203
+ "@type": "Production",
2204
+ "_label": "Test Part"
2205
+ }
1679
2206
  }
1680
- ]
1681
- })
1682
- do_frame(input: input, frame: frame, output: expected, processingMode: 'json-ld-1.1')
2207
+ }),
2208
+ frame: %({
2209
+ "@context": {
2210
+ "@version": 1.1,
2211
+ "@vocab": "http://example.org/vocab#",
2212
+ "Production": {
2213
+ "@context": {
2214
+ "part": {
2215
+ "@type": "@id",
2216
+ "@container": "@set"
2217
+ }
2218
+ }
2219
+ }
2220
+ },
2221
+ "@id": "http://example.org/1"
2222
+ }),
2223
+ output: %({
2224
+ "@context": {
2225
+ "@version": 1.1,
2226
+ "@vocab": "http://example.org/vocab#",
2227
+ "Production": {
2228
+ "@context": {
2229
+ "part": {
2230
+ "@type": "@id",
2231
+ "@container": "@set"
2232
+ }
2233
+ }
2234
+ }
2235
+ },
2236
+ "@id": "http://example.org/1",
2237
+ "@type": "HumanMadeObject",
2238
+ "produced_by": {
2239
+ "@type": "Production",
2240
+ "part": [{
2241
+ "@type": "Production",
2242
+ "_label": "Test Part"
2243
+ }],
2244
+ "_label": "Top Production"
2245
+ }
2246
+ }),
2247
+ processingMode: "json-ld-1.1"
2248
+ },
2249
+ "issue json-ld-framing#27": {
2250
+ input: %({
2251
+ "@id": "ex:cred",
2252
+ "ex:subject": {
2253
+ "@id": "ex:Subject",
2254
+ "ex:name": "the subject",
2255
+ "ex:knows": {
2256
+ "@id": "ex:issuer",
2257
+ "ex:name": "Someone else"
2258
+ }
2259
+ },
2260
+ "ex:proof": {
2261
+ "@graph": {
2262
+ "@type": "ex:Proof",
2263
+ "ex:name": "the proof",
2264
+ "ex:signer": [{
2265
+ "@id": "ex:Subject",
2266
+ "ex:name": "something different"
2267
+ }]
2268
+ }
2269
+ }
2270
+ }),
2271
+ frame: %({
2272
+ "@context": {
2273
+ "@version": 1.1,
2274
+ "proof": {"@id": "ex:proof", "@container": "@graph"}
2275
+ },
2276
+ "@graph": {
2277
+ "subject": {},
2278
+ "proof": {}
2279
+ }
2280
+ }),
2281
+ output: %({
2282
+ "@context": {
2283
+ "@version": 1.1,
2284
+ "proof": {
2285
+ "@id": "ex:proof",
2286
+ "@container": "@graph"
2287
+ }
2288
+ },
2289
+ "@id": "ex:cred",
2290
+ "ex:subject": {
2291
+ "@id": "ex:Subject",
2292
+ "ex:name": "the subject",
2293
+ "ex:knows": {
2294
+ "@id": "ex:issuer",
2295
+ "ex:name": "Someone else"
2296
+ }
2297
+ },
2298
+ "proof": {
2299
+ "@type": "ex:Proof",
2300
+ "ex:name": "the proof",
2301
+ "ex:signer": {
2302
+ "@id": "ex:Subject",
2303
+ "ex:name": "something different"
2304
+ }
2305
+ }
2306
+ }),
2307
+ processingMode: "json-ld-1.1"
2308
+ }
2309
+ }.each do |title, params|
2310
+ it title do
2311
+ do_frame(params)
2312
+ end
1683
2313
  end
1684
2314
  end
1685
2315
 
@@ -1689,7 +2319,12 @@ describe JSON::LD::API do
1689
2319
  input = ::JSON.parse(input) if input.is_a?(String)
1690
2320
  frame = ::JSON.parse(frame) if frame.is_a?(String)
1691
2321
  output = ::JSON.parse(output) if output.is_a?(String)
1692
- jld = JSON::LD::API.frame(input, frame, logger: logger, processingMode: processingMode)
2322
+ jld = nil
2323
+ if params[:write]
2324
+ expect{jld = JSON::LD::API.frame(input, frame, logger: logger, processingMode: processingMode)}.to write(params[:write]).to(:error)
2325
+ else
2326
+ expect{jld = JSON::LD::API.frame(input, frame, logger: logger, processingMode: processingMode)}.not_to write.to(:error)
2327
+ end
1693
2328
  expect(jld).to produce_jsonld(output, logger)
1694
2329
 
1695
2330
  # Compare expanded jld/output too to make sure list values remain ordered