json-ld 3.1.1 → 3.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -16,6 +16,8 @@ module JSON::LD
16
16
  # @return RDF::Resource the subject of this item
17
17
  def item_to_rdf(item, graph_name: nil, &block)
18
18
  # Just return value object as Term
19
+ return unless item
20
+
19
21
  if value?(item)
20
22
  value, datatype = item.fetch('@value'), item.fetch('@type', nil)
21
23
 
@@ -76,11 +78,13 @@ module JSON::LD
76
78
  return parse_list(item['@list'], graph_name: graph_name, &block)
77
79
  end
78
80
 
79
- # Skip if '@id' is nil
80
- subject = if item.has_key?('@id')
81
- item['@id'].nil? ? nil : as_resource(item['@id'])
82
- else
83
- node
81
+ subject = case item['@id']
82
+ when nil then node
83
+ when String then as_resource(item['@id'])
84
+ when Object
85
+ # Embedded statement
86
+ # (No error checking, as this is done in expansion)
87
+ to_enum(:item_to_rdf, item['@id']).to_a.first
84
88
  end
85
89
 
86
90
  #log_debug("item_to_rdf") {"subject: #{subject.to_ntriples rescue 'malformed rdf'}"}
@@ -93,7 +93,7 @@ module JSON::LD
93
93
  datatype: RDF::URI,
94
94
  control: :url2,
95
95
  on: ["--context CONTEXT"],
96
- description: "Context to use when compacting.") {|arg| RDF::URI(arg)},
96
+ description: "Context to use when compacting.") {|arg| RDF::URI(arg).absolute? ? RDF::URI(arg) : StringIO.new(File.read(arg))},
97
97
  RDF::CLI::Option.new(
98
98
  symbol: :embed,
99
99
  datatype: %w(@always @once @never),
@@ -107,6 +107,13 @@ module JSON::LD
107
107
  control: :checkbox,
108
108
  on: ["--[no-]explicit"],
109
109
  description: "Only include explicitly declared properties in output (false)") {|arg| arg},
110
+ RDF::CLI::Option.new(
111
+ symbol: :frame,
112
+ datatype: RDF::URI,
113
+ control: :url2,
114
+ use: :required,
115
+ on: ["--frame FRAME"],
116
+ description: "Frame to use when serializing.") {|arg| RDF::URI(arg).absolute? ? RDF::URI(arg) : StringIO.new(File.read(arg))},
110
117
  RDF::CLI::Option.new(
111
118
  symbol: :lowercaseLanguage,
112
119
  datatype: TrueClass,
@@ -137,7 +144,7 @@ module JSON::LD
137
144
  default: 'null',
138
145
  control: :select,
139
146
  on: ["--rdf-direction DIR", %w(i18n-datatype compound-literal)],
140
- description: "How to serialize literal direction (i18n-datatype compound-literal)") {|arg| RDF::URI(arg)},
147
+ description: "How to serialize literal direction (i18n-datatype compound-literal)") {|arg| arg},
141
148
  RDF::CLI::Option.new(
142
149
  symbol: :requireAll,
143
150
  datatype: TrueClass,
@@ -202,7 +209,7 @@ module JSON::LD
202
209
  end
203
210
 
204
211
  ##
205
- # Initializes the RDF-LD writer instance.
212
+ # Initializes the JSON-LD writer instance.
206
213
  #
207
214
  # @param [IO, File] output
208
215
  # the output stream
@@ -564,6 +564,7 @@ describe JSON::LD::API do
564
564
  documentUrl: "http://example.com/context")
565
565
  end
566
566
  it "uses referenced context" do
567
+ JSON::LD::Context.instance_variable_set(:@cache, nil)
567
568
  input = ::JSON.parse %({
568
569
  "http://example.com/b": "c"
569
570
  })
@@ -56,15 +56,8 @@ describe JSON::LD::Context do
56
56
  describe "#parse" do
57
57
  context "remote" do
58
58
 
59
- it "retrieves and parses a remote context document" do
60
- JSON::LD::Context::PRELOADED.clear
61
- expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc)
62
- ec = subject.parse("http://example.com/context")
63
- expect(ec.provided_context).to produce("http://example.com/context", logger)
64
- end
65
-
66
59
  it "fails given a missing remote @context" do
67
- JSON::LD::Context::PRELOADED.clear
60
+ JSON::LD::Context.instance_variable_set(:@cache, nil)
68
61
  expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_raise(IOError)
69
62
  expect {subject.parse("http://example.com/context")}.to raise_error(JSON::LD::JsonLdError::LoadingRemoteContextFailed, %r{http://example.com/context})
70
63
  end
@@ -116,7 +109,7 @@ describe JSON::LD::Context do
116
109
  documentUrl: "http://example.com/context",
117
110
  contentType: "text/html")
118
111
 
119
- JSON::LD::Context::PRELOADED.clear
112
+ JSON::LD::Context.instance_variable_set(:@cache, nil)
120
113
  expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc)
121
114
  ec = subject.parse("http://example.com/context")
122
115
  expect(ec.send(:mappings)).to produce({
@@ -154,7 +147,7 @@ describe JSON::LD::Context do
154
147
  ),
155
148
  documentUrl: "http://example.com/context",
156
149
  contentType: "text/html")
157
- JSON::LD::Context::PRELOADED.clear
150
+ JSON::LD::Context.instance_variable_set(:@cache, nil)
158
151
  expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc)
159
152
  ec = subject.parse("http://example.com/context")
160
153
  expect(ec.send(:mappings)).to produce({
@@ -170,7 +163,7 @@ describe JSON::LD::Context do
170
163
  end
171
164
 
172
165
  it "parses a referenced context at a relative URI" do
173
- JSON::LD::Context::PRELOADED.clear
166
+ JSON::LD::Context.instance_variable_set(:@cache, nil)
174
167
  rd1 = JSON::LD::API::RemoteDocument.new(%({"@context": "context"}), base_uri: "http://example.com/c1")
175
168
  expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/c1", anything).and_yield(rd1)
176
169
  expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc)
@@ -185,17 +178,11 @@ describe JSON::LD::Context do
185
178
 
186
179
  context "remote with local mappings" do
187
180
  let(:ctx) {["http://example.com/context", {"integer" => "xsd:integer"}]}
188
- before {JSON::LD::Context::PRELOADED.clear}
181
+ before {JSON::LD::Context.instance_variable_set(:@cache, nil)}
189
182
  it "retrieves and parses a remote context document" do
190
183
  expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc)
191
184
  subject.parse(ctx)
192
185
  end
193
-
194
- it "does not use passed context as provided_context" do
195
- expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc)
196
- ec = subject.parse(ctx)
197
- expect(ec.provided_context).to produce(ctx, logger)
198
- end
199
186
  end
200
187
 
201
188
  context "pre-loaded remote" do
@@ -206,7 +193,7 @@ describe JSON::LD::Context do
206
193
  )
207
194
  JSON::LD::Context.alias_preloaded("https://example.com/preloaded", "http://example.com/preloaded")
208
195
  }
209
- after(:all) {JSON::LD::Context::PRELOADED.clear}
196
+ after(:all) {JSON::LD::Context.instance_variable_set(:@cache, nil)}
210
197
 
211
198
  it "does not load referenced context" do
212
199
  expect(JSON::LD::API).not_to receive(:documentLoader).with(ctx, anything)
@@ -249,6 +236,7 @@ describe JSON::LD::Context do
249
236
  end
250
237
 
251
238
  it "merges definitions from remote contexts" do
239
+ JSON::LD::Context.instance_variable_set(:@cache, nil)
252
240
  expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc)
253
241
  rd2 = JSON::LD::API::RemoteDocument.new(%q({
254
242
  "@context": {
@@ -476,7 +464,7 @@ describe JSON::LD::Context do
476
464
  end
477
465
 
478
466
  context "@import" do
479
- before(:each) {JSON::LD::Context::PRELOADED.clear}
467
+ before(:each) {JSON::LD::Context.instance_variable_set(:@cache, nil)}
480
468
  it "generates an InvalidImportValue error if not a string" do
481
469
  expect {subject.parse({'@version' => 1.1, '@import' => true})}.to raise_error(JSON::LD::JsonLdError::InvalidImportValue)
482
470
  end
@@ -503,7 +491,7 @@ describe JSON::LD::Context do
503
491
  "@type as object" => {"foo" => {"@type" => {}}},
504
492
  "@type as array" => {"foo" => {"@type" => []}},
505
493
  "@type as @list" => {"foo" => {"@type" => "@list"}},
506
- "@type as @none" => {"@version": 1.1, "foo" => {"@type" => "@none"}},
494
+ "@type as @none" => {"@version" => 1.1, "foo" => {"@type" => "@none"}},
507
495
  "@type as @set" => {"foo" => {"@type" => "@set"}},
508
496
  "@container as object" => {"foo" => {"@container" => {}}},
509
497
  "@container as empty array" => {"foo" => {"@container" => []}},
@@ -642,26 +630,8 @@ describe JSON::LD::Context do
642
630
  end
643
631
  end
644
632
 
645
- describe "#merge!" do
646
- it "updates context with components from new" do
647
- c2 = JSON::LD::Context.parse({'foo' => "http://example.com/"})
648
- cm = context.merge!(c2)
649
- expect(cm).to equal context
650
- expect(cm).not_to equal c2
651
- expect(cm.term_definitions).to eq c2.term_definitions
652
- end
653
- end
654
-
655
633
  describe "#serialize" do
656
- before {JSON::LD::Context::PRELOADED.clear}
657
- it "context document" do
658
- expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc)
659
- ec = subject.parse("http://example.com/context")
660
- expect(ec.serialize).to produce({
661
- "@context" => "http://example.com/context"
662
- }, logger)
663
- end
664
-
634
+ before {JSON::LD::Context.instance_variable_set(:@cache, nil)}
665
635
  it "context hash" do
666
636
  ctx = {"foo" => "http://example.com/"}
667
637
 
@@ -693,7 +663,7 @@ describe JSON::LD::Context do
693
663
 
694
664
  it "term mappings" do
695
665
  c = subject.
696
- parse({'foo' => "http://example.com/"}).send(:clear_provided_context)
666
+ parse({'foo' => "http://example.com/"})
697
667
  expect(c.serialize).to produce({
698
668
  "@context" => {
699
669
  "foo" => "http://example.com/"
@@ -705,7 +675,7 @@ describe JSON::LD::Context do
705
675
  it "@context" do
706
676
  expect(subject.parse({
707
677
  "foo" => {"@id" => "http://example.com/", "@context" => {"bar" => "http://example.com/baz"}}
708
- }).send(:clear_provided_context).
678
+ }).
709
679
  serialize).to produce({
710
680
  "@context" => {
711
681
  "foo" => {
@@ -721,7 +691,6 @@ describe JSON::LD::Context do
721
691
  'xsd' => "http://www.w3.org/2001/XMLSchema#",
722
692
  'homepage' => {'@id' => RDF::Vocab::FOAF.homepage.to_s, '@type' => '@id'}
723
693
  }).
724
- send(:clear_provided_context).
725
694
  serialize).to produce({
726
695
  "@context" => {
727
696
  "xsd" => RDF::XSD.to_uri.to_s,
@@ -734,7 +703,6 @@ describe JSON::LD::Context do
734
703
  expect(subject.parse({
735
704
  'knows' => {'@id' => RDF::Vocab::FOAF.knows.to_s, '@container' => '@list'}
736
705
  }).
737
- send(:clear_provided_context).
738
706
  serialize).to produce({
739
707
  "@context" => {
740
708
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@container" => "@list"}
@@ -746,7 +714,6 @@ describe JSON::LD::Context do
746
714
  expect(subject.parse({
747
715
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@container" => "@set"}
748
716
  }).
749
- send(:clear_provided_context).
750
717
  serialize).to produce({
751
718
  "@context" => {
752
719
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@container" => "@set"}
@@ -758,7 +725,6 @@ describe JSON::LD::Context do
758
725
  expect(subject.parse({
759
726
  "name" => {"@id" => RDF::Vocab::FOAF.name.to_s, "@language" => "en"}
760
727
  }).
761
- send(:clear_provided_context).
762
728
  serialize).to produce({
763
729
  "@context" => {
764
730
  "name" => {"@id" => RDF::Vocab::FOAF.name.to_s, "@language" => "en"}
@@ -771,7 +737,6 @@ describe JSON::LD::Context do
771
737
  "@language" => 'en',
772
738
  "name" => {"@id" => RDF::Vocab::FOAF.name.to_s, "@language" => 'en'}
773
739
  }).
774
- send(:clear_provided_context).
775
740
  serialize).to produce({
776
741
  "@context" => {
777
742
  "@language" => 'en',
@@ -785,7 +750,6 @@ describe JSON::LD::Context do
785
750
  "@language" => 'en',
786
751
  "name" => {"@id" => RDF::Vocab::FOAF.name.to_s, "@language" => "de"}
787
752
  }).
788
- send(:clear_provided_context).
789
753
  serialize).to produce({
790
754
  "@context" => {
791
755
  "@language" => 'en',
@@ -799,7 +763,6 @@ describe JSON::LD::Context do
799
763
  "@language" => 'en',
800
764
  "name" => {"@id" => RDF::Vocab::FOAF.name.to_s, "@language" => nil}
801
765
  }).
802
- send(:clear_provided_context).
803
766
  serialize).to produce({
804
767
  "@context" => {
805
768
  "@language" => 'en',
@@ -812,7 +775,6 @@ describe JSON::LD::Context do
812
775
  expect(subject.parse({
813
776
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@type" => "@id", "@container" => "@list"}
814
777
  }).
815
- send(:clear_provided_context).
816
778
  serialize).to produce({
817
779
  "@context" => {
818
780
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@type" => "@id", "@container" => "@list"}
@@ -824,7 +786,6 @@ describe JSON::LD::Context do
824
786
  expect(subject.parse({
825
787
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@type" => "@id", "@container" => "@set"}
826
788
  }).
827
- send(:clear_provided_context).
828
789
  serialize).to produce({
829
790
  "@context" => {
830
791
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@type" => "@id", "@container" => "@set"}
@@ -836,7 +797,6 @@ describe JSON::LD::Context do
836
797
  expect(subject.parse({
837
798
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@type" => "@json"}
838
799
  }).
839
- send(:clear_provided_context).
840
800
  serialize).to produce({
841
801
  "@context" => {
842
802
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@type" => "@json"}
@@ -851,7 +811,6 @@ describe JSON::LD::Context do
851
811
  "@container" => "@list"
852
812
  }
853
813
  }).
854
- send(:clear_provided_context).
855
814
  serialize).to produce({
856
815
  "@context" => {
857
816
  "foaf" => RDF::Vocab::FOAF.to_uri.to_s,
@@ -867,7 +826,6 @@ describe JSON::LD::Context do
867
826
  "id" => "@id",
868
827
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@container" => "@list"}
869
828
  }).
870
- send(:clear_provided_context).
871
829
  serialize).to produce({
872
830
  "@context" => {
873
831
  "id" => "@id",
@@ -884,7 +842,6 @@ describe JSON::LD::Context do
884
842
  "@type" => "@id"
885
843
  }
886
844
  }).
887
- send(:clear_provided_context).
888
845
  serialize).to produce({
889
846
  "@context" => {
890
847
  "foaf" => RDF::Vocab::FOAF.to_uri.to_s,
@@ -902,7 +859,6 @@ describe JSON::LD::Context do
902
859
  "type" => "@type",
903
860
  "foaf:homepage" => {"@type" => "@id"}
904
861
  }).
905
- send(:clear_provided_context).
906
862
  serialize).to produce({
907
863
  "@context" => {
908
864
  "foaf" => RDF::Vocab::FOAF.to_uri.to_s,
@@ -917,7 +873,6 @@ describe JSON::LD::Context do
917
873
  "container" => "@container",
918
874
  "knows" => {"@id" => RDF::Vocab::FOAF.knows.to_s, "@container" => "@list"}
919
875
  }).
920
- send(:clear_provided_context).
921
876
  serialize).to produce({
922
877
  "@context" => {
923
878
  "container" => "@container",
@@ -931,7 +886,6 @@ describe JSON::LD::Context do
931
886
  "ex" => 'http://example.org/',
932
887
  "term" => {"@id" => "ex:term", "@type" => "ex:datatype"}
933
888
  }).
934
- send(:clear_provided_context).
935
889
  serialize).to produce({
936
890
  "@context" => {
937
891
  "ex" => 'http://example.org/',
@@ -945,7 +899,6 @@ describe JSON::LD::Context do
945
899
  "@vocab" => 'http://example.org/',
946
900
  "term" => {"@id" => "http://example.org/term", "@type" => "datatype"}
947
901
  }).
948
- send(:clear_provided_context).
949
902
  serialize).to produce({
950
903
  "@context" => {
951
904
  "@vocab" => 'http://example.org/',
@@ -954,11 +907,13 @@ describe JSON::LD::Context do
954
907
  }, logger)
955
908
  end
956
909
 
957
- context "extra keys or values" do
910
+ context "invalid term definitions" do
958
911
  {
959
- "extra key" => {
960
- input: {"foo" => {"@id" => "http://example.com/foo", "@baz" => "foobar"}},
961
- result: {"@context" => {"foo" => {"@id" => "http://example.com/foo", "@baz" => "foobar"}}}
912
+ "empty term": {
913
+ input: {"" => "http://blank-term/"}
914
+ },
915
+ "extra key": {
916
+ input: {"foo" => {"@id" => "http://example.com/foo", "@baz" => "foobar"}}
962
917
  }
963
918
  }.each do |title, params|
964
919
  it title do
@@ -975,7 +930,6 @@ describe JSON::LD::Context do
975
930
  '@base' => 'http://base/',
976
931
  '@vocab' => 'http://vocab/',
977
932
  'ex' => 'http://example.org/',
978
- '' => 'http://empty/',
979
933
  '_' => 'http://underscore/'
980
934
  })
981
935
  }
@@ -1039,7 +993,6 @@ describe JSON::LD::Context do
1039
993
  '@base' => 'http://base/base',
1040
994
  '@vocab' => 'http://vocab/',
1041
995
  'ex' => 'http://example.org/',
1042
- '' => 'http://empty/',
1043
996
  '_' => 'http://underscore/'
1044
997
  })
1045
998
  }
@@ -1119,7 +1072,6 @@ describe JSON::LD::Context do
1119
1072
  "unmapped" => ["foo", RDF::URI("http://vocab/foo")],
1120
1073
  "relative" => ["foo/bar", RDF::URI("http://vocab/foo/bar")],
1121
1074
  "dotseg" => ["../foo/bar", RDF::URI("http://vocab/../foo/bar")],
1122
- "empty term" => ["", RDF::URI("http://empty/")],
1123
1075
  "another abs IRI"=>["ex://foo", RDF::URI("ex://foo")],
1124
1076
  "absolute IRI looking like a compact IRI" =>
1125
1077
  ["foo:bar", RDF::URI("foo:bar")],
@@ -1138,7 +1090,6 @@ describe JSON::LD::Context do
1138
1090
  '@base' => 'http://base/base',
1139
1091
  '@vocab' => '',
1140
1092
  'ex' => 'http://example.org/',
1141
- '' => 'http://empty/',
1142
1093
  '_' => 'http://underscore/'
1143
1094
  })
1144
1095
  }
@@ -1153,7 +1104,6 @@ describe JSON::LD::Context do
1153
1104
  "unmapped" => ["foo", RDF::URI("http://base/basefoo")],
1154
1105
  "relative" => ["foo/bar", RDF::URI("http://base/basefoo/bar")],
1155
1106
  "dotseg" => ["../foo/bar", RDF::URI("http://base/base../foo/bar")],
1156
- "empty term" => ["", RDF::URI("http://empty/")],
1157
1107
  "another abs IRI"=>["ex://foo", RDF::URI("ex://foo")],
1158
1108
  "absolute IRI looking like a compact IRI" =>
1159
1109
  ["foo:bar", RDF::URI("foo:bar")],
@@ -1183,7 +1133,6 @@ describe JSON::LD::Context do
1183
1133
  '@base' => 'http://base/',
1184
1134
  "xsd" => "http://www.w3.org/2001/XMLSchema#",
1185
1135
  'ex' => 'http://example.org/',
1186
- '' => 'http://empty/',
1187
1136
  '_' => 'http://underscore/',
1188
1137
  'rex' => {'@reverse' => "ex"},
1189
1138
  'lex' => {'@id' => 'ex', '@language' => 'en'},
@@ -1258,7 +1207,7 @@ describe JSON::LD::Context do
1258
1207
  it "does not use @vocab if it would collide with a term" do
1259
1208
  subject.set_mapping("name", "http://xmlns.com/foaf/0.1/name")
1260
1209
  subject.set_mapping("ex", nil)
1261
- expect(subject.compact_iri("http://example.org/name", position: :predicate)).
1210
+ expect(subject.compact_iri("http://example.org/name", vocab: true)).
1262
1211
  not_to produce("name", logger)
1263
1212
  end
1264
1213
 
@@ -1390,7 +1339,6 @@ describe JSON::LD::Context do
1390
1339
  "absolute IRI" => ["http://example.com/", "http://example.com/"],
1391
1340
  "prefix:suffix" => ["ex:suffix", "http://example.org/suffix"],
1392
1341
  "keyword" => ["@type", "@type"],
1393
- "empty" => [":suffix", "http://empty/suffix"],
1394
1342
  "unmapped" => ["foo", "foo"],
1395
1343
  "bnode" => [JSON::LD::JsonLdError:: IRIConfusedWithPrefix, RDF::Node("a")],
1396
1344
  "relative" => ["foo/bar", "http://base/foo/bar"],
@@ -1412,7 +1360,6 @@ describe JSON::LD::Context do
1412
1360
  "absolute IRI" => ["http://example.com/", "http://example.com/"],
1413
1361
  "prefix:suffix" => ["suffix", "http://example.org/suffix"],
1414
1362
  "keyword" => ["@type", "@type"],
1415
- "empty" => [":suffix", "http://empty/suffix"],
1416
1363
  "unmapped" => ["foo", "foo"],
1417
1364
  "bnode" => [JSON::LD::JsonLdError:: IRIConfusedWithPrefix, RDF::Node("a")],
1418
1365
  "relative" => ["http://base/foo/bar", "http://base/foo/bar"],
@@ -1543,7 +1490,7 @@ describe JSON::LD::Context do
1543
1490
  })
1544
1491
  end
1545
1492
  it "Compact @id that is a property IRI when @container is @list" do
1546
- expect(ctx.compact_iri("http://example.org/ns#property", position: :subject)).
1493
+ expect(ctx.compact_iri("http://example.org/ns#property", vocab: false)).
1547
1494
  to produce("ex:property", logger)
1548
1495
  end
1549
1496
  end
@@ -2909,6 +2909,26 @@ describe JSON::LD::API do
2909
2909
  validate: true,
2910
2910
  exception: JSON::LD::JsonLdError::InvalidTermDefinition
2911
2911
  },
2912
+ "Applies property scoped contexts which are aliases of @nest": {
2913
+ input: %({
2914
+ "@context": {
2915
+ "@version": 1.1,
2916
+ "@vocab": "http://example.org/",
2917
+ "nest": {
2918
+ "@id": "@nest",
2919
+ "@context": {
2920
+ "@vocab": "http://example.org/nest/"
2921
+ }
2922
+ }
2923
+ },
2924
+ "nest": {
2925
+ "property": "should be in /nest"
2926
+ }
2927
+ }),
2928
+ output: %([{
2929
+ "http://example.org/nest/property": [{"@value": "should be in /nest"}]
2930
+ }])
2931
+ }
2912
2932
  }.each do |title, params|
2913
2933
  it(title) {run_expand({processingMode: "json-ld-1.1"}.merge(params))}
2914
2934
  end
@@ -3356,6 +3376,254 @@ describe JSON::LD::API do
3356
3376
  end
3357
3377
  end
3358
3378
 
3379
+ context "JSON-LD*" do
3380
+ {
3381
+ "node with embedded subject without rdfstar option": {
3382
+ input: %({
3383
+ "@id": {
3384
+ "@id": "ex:rei",
3385
+ "ex:prop": "value"
3386
+ },
3387
+ "ex:prop": "value2"
3388
+ }),
3389
+ exception: JSON::LD::JsonLdError::InvalidIdValue
3390
+ },
3391
+ }.each do |title, params|
3392
+ it(title) {run_expand params}
3393
+ end
3394
+
3395
+ {
3396
+ "node with embedded subject having no @id": {
3397
+ input: %({
3398
+ "@id": {
3399
+ "ex:prop": "value"
3400
+ },
3401
+ "ex:prop": "value2"
3402
+ }),
3403
+ output: %([{
3404
+ "@id": {
3405
+ "ex:prop": [{"@value": "value"}]
3406
+ },
3407
+ "ex:prop": [{"@value": "value2"}]
3408
+ }])
3409
+ },
3410
+ "node with embedded subject having IRI @id": {
3411
+ input: %({
3412
+ "@id": {
3413
+ "@id": "ex:rei",
3414
+ "ex:prop": "value"
3415
+ },
3416
+ "ex:prop": "value2"
3417
+ }),
3418
+ output: %([{
3419
+ "@id": {
3420
+ "@id": "ex:rei",
3421
+ "ex:prop": [{"@value": "value"}]
3422
+ },
3423
+ "ex:prop": [{"@value": "value2"}]
3424
+ }])
3425
+ },
3426
+ "node with embedded subject having BNode @id": {
3427
+ input: %({
3428
+ "@id": {
3429
+ "@id": "_:rei",
3430
+ "ex:prop": "value"
3431
+ },
3432
+ "ex:prop": "value2"
3433
+ }),
3434
+ output: %([{
3435
+ "@id": {
3436
+ "@id": "_:rei",
3437
+ "ex:prop": [{"@value": "value"}]
3438
+ },
3439
+ "ex:prop": [{"@value": "value2"}]
3440
+ }])
3441
+ },
3442
+ "node with embedded subject having a type": {
3443
+ input: %({
3444
+ "@id": {
3445
+ "@id": "ex:rei",
3446
+ "@type": "ex:Type"
3447
+ },
3448
+ "ex:prop": "value2"
3449
+ }),
3450
+ output: %([{
3451
+ "@id": {
3452
+ "@id": "ex:rei",
3453
+ "@type": ["ex:Type"]
3454
+ },
3455
+ "ex:prop": [{"@value": "value2"}]
3456
+ }])
3457
+ },
3458
+ "node with embedded subject having an IRI value": {
3459
+ input: %({
3460
+ "@id": {
3461
+ "@id": "ex:rei",
3462
+ "ex:prop": {"@id": "ex:value"}
3463
+ },
3464
+ "ex:prop": "value2"
3465
+ }),
3466
+ output: %([{
3467
+ "@id": {
3468
+ "@id": "ex:rei",
3469
+ "ex:prop": [{"@id": "ex:value"}]
3470
+ },
3471
+ "ex:prop": [{"@value": "value2"}]
3472
+ }])
3473
+ },
3474
+ "node with embedded subject having an BNode value": {
3475
+ input: %({
3476
+ "@id": {
3477
+ "@id": "ex:rei",
3478
+ "ex:prop": {"@id": "_:value"}
3479
+ },
3480
+ "ex:prop": "value2"
3481
+ }),
3482
+ output: %([{
3483
+ "@id": {
3484
+ "@id": "ex:rei",
3485
+ "ex:prop": [{"@id": "_:value"}]
3486
+ },
3487
+ "ex:prop": [{"@value": "value2"}]
3488
+ }])
3489
+ },
3490
+ "node with recursive embedded subject": {
3491
+ input: %({
3492
+ "@id": {
3493
+ "@id": {
3494
+ "@id": "ex:rei",
3495
+ "ex:prop": "value3"
3496
+ },
3497
+ "ex:prop": "value"
3498
+ },
3499
+ "ex:prop": "value2"
3500
+ }),
3501
+ output: %([{
3502
+ "@id": {
3503
+ "@id": {
3504
+ "@id": "ex:rei",
3505
+ "ex:prop": [{"@value": "value3"}]
3506
+ },
3507
+ "ex:prop": [{"@value": "value"}]
3508
+ },
3509
+ "ex:prop": [{"@value": "value2"}]
3510
+ }])
3511
+ },
3512
+ "illegal node with subject having no property": {
3513
+ input: %({
3514
+ "@id": {
3515
+ "@id": "ex:rei"
3516
+ },
3517
+ "ex:prop": "value3"
3518
+ }),
3519
+ exception: JSON::LD::JsonLdError::InvalidEmbeddedNode
3520
+ },
3521
+ "illegal node with subject having multiple properties": {
3522
+ input: %({
3523
+ "@id": {
3524
+ "@id": "ex:rei",
3525
+ "ex:prop": ["value1", "value2"]
3526
+ },
3527
+ "ex:prop": "value3"
3528
+ }),
3529
+ exception: JSON::LD::JsonLdError::InvalidEmbeddedNode
3530
+ },
3531
+ "illegal node with subject having multiple types": {
3532
+ input: %({
3533
+ "@id": {
3534
+ "@id": "ex:rei",
3535
+ "@type": ["ex:Type1", "ex:Type2"]
3536
+ },
3537
+ "ex:prop": "value3"
3538
+ }),
3539
+ exception: JSON::LD::JsonLdError::InvalidEmbeddedNode
3540
+ },
3541
+ "illegal node with subject having type and property": {
3542
+ input: %({
3543
+ "@id": {
3544
+ "@id": "ex:rei",
3545
+ "@type": "ex:Type",
3546
+ "ex:prop": "value"
3547
+ },
3548
+ "ex:prop": "value2"
3549
+ }),
3550
+ exception: JSON::LD::JsonLdError::InvalidEmbeddedNode
3551
+ },
3552
+ "node with embedded object": {
3553
+ input: %({
3554
+ "@id": "ex:subj",
3555
+ "ex:value": {
3556
+ "@id": {
3557
+ "@id": "ex:rei",
3558
+ "ex:prop": "value"
3559
+ }
3560
+ }
3561
+ }),
3562
+ output: %([{
3563
+ "@id": "ex:subj",
3564
+ "ex:value": [{
3565
+ "@id": {
3566
+ "@id": "ex:rei",
3567
+ "ex:prop": [{"@value": "value"}]
3568
+ }
3569
+ }]
3570
+ }])
3571
+ },
3572
+ "illegal node with embedded object having properties": {
3573
+ input: %({
3574
+ "@id": "ex:subj",
3575
+ "ex:value": {
3576
+ "@id": {
3577
+ "@id": "ex:rei",
3578
+ "ex:prop": "value"
3579
+ },
3580
+ "ex:prop": "value2"
3581
+ }
3582
+ }),
3583
+ output: %([{
3584
+ "@id": "ex:subj",
3585
+ "ex:value": [{
3586
+ "@id": {
3587
+ "@id": "ex:rei",
3588
+ "ex:prop": [{"@value": "value"}]
3589
+ },
3590
+ "ex:prop": [{"@value": "value2"}]
3591
+ }]
3592
+ }])
3593
+ },
3594
+ "node with recursive embedded object": {
3595
+ input: %({
3596
+ "@id": "ex:subj",
3597
+ "ex:value": {
3598
+ "@id": {
3599
+ "@id": {
3600
+ "@id": "ex:rei",
3601
+ "ex:prop": "value3"
3602
+ },
3603
+ "ex:prop": "value"
3604
+ },
3605
+ "ex:prop": "value2"
3606
+ }
3607
+ }),
3608
+ output: %([{
3609
+ "@id": "ex:subj",
3610
+ "ex:value": [{
3611
+ "@id": {
3612
+ "@id": {
3613
+ "@id": "ex:rei",
3614
+ "ex:prop": [{"@value": "value3"}]
3615
+ },
3616
+ "ex:prop":[{"@value": "value"}]
3617
+ },
3618
+ "ex:prop": [{"@value": "value2"}]
3619
+ }]
3620
+ }])
3621
+ },
3622
+ }.each do |title, params|
3623
+ it(title) {run_expand params.merge(rdfstar: true)}
3624
+ end
3625
+ end
3626
+
3359
3627
  begin
3360
3628
  require 'nokogiri'
3361
3629
  rescue LoadError
@@ -3366,7 +3634,7 @@ describe JSON::LD::API do
3366
3634
  %w(Nokogiri REXML).each do |impl|
3367
3635
  next unless Module.constants.map(&:to_s).include?(impl)
3368
3636
  context impl do
3369
- before(:all) {@library = impl.downcase.to_s.to_sym}
3637
+ let(:library) {impl.downcase.to_s.to_sym}
3370
3638
 
3371
3639
  {
3372
3640
  "Expands embedded JSON-LD script element": {
@@ -3505,9 +3773,9 @@ describe JSON::LD::API do
3505
3773
  ]),
3506
3774
  extractAllScripts: true
3507
3775
  },
3508
- "Expands as empty with no script element": {
3776
+ "Errors no script element": {
3509
3777
  input: %(<html><head></head></html>),
3510
- output: %([])
3778
+ exception: JSON::LD::JsonLdError::LoadingDocumentFailed
3511
3779
  },
3512
3780
  "Expands as empty with no script element and extractAllScripts": {
3513
3781
  input: %(<html><head></head></html>),
@@ -3619,7 +3887,7 @@ describe JSON::LD::API do
3619
3887
  </head>
3620
3888
  </html>),
3621
3889
  base: "http://example.org/doc#third",
3622
- exception: JSON::LD::JsonLdError::InvalidScriptElement
3890
+ exception: JSON::LD::JsonLdError::LoadingDocumentFailed
3623
3891
  },
3624
3892
  "Errors if targeted element is not a script element": {
3625
3893
  input: %(
@@ -3636,7 +3904,7 @@ describe JSON::LD::API do
3636
3904
  </head>
3637
3905
  </html>),
3638
3906
  base: "http://example.org/doc#first",
3639
- exception: JSON::LD::JsonLdError::InvalidScriptElement
3907
+ exception: JSON::LD::JsonLdError::LoadingDocumentFailed
3640
3908
  },
3641
3909
  "Errors if targeted element does not have type application/ld+json": {
3642
3910
  input: %(
@@ -3653,7 +3921,7 @@ describe JSON::LD::API do
3653
3921
  </head>
3654
3922
  </html>),
3655
3923
  base: "http://example.org/doc#first",
3656
- exception: JSON::LD::JsonLdError::InvalidScriptElement
3924
+ exception: JSON::LD::JsonLdError::LoadingDocumentFailed
3657
3925
  },
3658
3926
  "Errors if uncommented script text contains comment": {
3659
3927
  input: %(
@@ -3722,10 +3990,10 @@ describe JSON::LD::API do
3722
3990
  },
3723
3991
  }.each do |title, params|
3724
3992
  it(title) do
3725
- skip "rexml" if params[:not] == @library
3726
- params[:input] = StringIO.new(params[:input])
3993
+ skip "rexml" if params[:not] == library
3994
+ params = params.merge(input: StringIO.new(params[:input]))
3727
3995
  params[:input].send(:define_singleton_method, :content_type) {"text/html"}
3728
- run_expand params.merge(validate: true, library: @library)
3996
+ run_expand params.merge(validate: true, library: library)
3729
3997
  end
3730
3998
  end
3731
3999
  end