yaml-ld 0.0.1

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 (71) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +1 -0
  3. data/README.md +150 -0
  4. data/UNLICENSE +24 -0
  5. data/VERSION +1 -0
  6. data/lib/yaml_ld/api.rb +295 -0
  7. data/lib/yaml_ld/format.rb +56 -0
  8. data/lib/yaml_ld/reader.rb +40 -0
  9. data/lib/yaml_ld/version.rb +20 -0
  10. data/lib/yaml_ld/writer.rb +42 -0
  11. data/lib/yaml_ld.rb +37 -0
  12. data/spec/api_spec.rb +92 -0
  13. data/spec/compact_spec.rb +358 -0
  14. data/spec/expand_spec.rb +565 -0
  15. data/spec/flatten_spec.rb +225 -0
  16. data/spec/format_spec.rb +54 -0
  17. data/spec/frame_spec.rb +662 -0
  18. data/spec/from_rdf_spec.rb +730 -0
  19. data/spec/matchers.rb +22 -0
  20. data/spec/reader_spec.rb +138 -0
  21. data/spec/spec_helper.rb +265 -0
  22. data/spec/support/extensions.rb +44 -0
  23. data/spec/test-files/test-1-compacted.jsonld +10 -0
  24. data/spec/test-files/test-1-context.jsonld +7 -0
  25. data/spec/test-files/test-1-expanded.jsonld +5 -0
  26. data/spec/test-files/test-1-input.yamlld +8 -0
  27. data/spec/test-files/test-1-rdf.ttl +8 -0
  28. data/spec/test-files/test-2-compacted.jsonld +20 -0
  29. data/spec/test-files/test-2-context.jsonld +7 -0
  30. data/spec/test-files/test-2-expanded.jsonld +16 -0
  31. data/spec/test-files/test-2-input.yamlld +16 -0
  32. data/spec/test-files/test-2-rdf.ttl +14 -0
  33. data/spec/test-files/test-3-compacted.jsonld +11 -0
  34. data/spec/test-files/test-3-context.jsonld +8 -0
  35. data/spec/test-files/test-3-expanded.jsonld +10 -0
  36. data/spec/test-files/test-3-input.yamlld +13 -0
  37. data/spec/test-files/test-3-rdf.ttl +8 -0
  38. data/spec/test-files/test-4-compacted.jsonld +10 -0
  39. data/spec/test-files/test-4-context.jsonld +7 -0
  40. data/spec/test-files/test-4-expanded.jsonld +6 -0
  41. data/spec/test-files/test-4-input.yamlld +9 -0
  42. data/spec/test-files/test-4-rdf.ttl +5 -0
  43. data/spec/test-files/test-5-compacted.jsonld +13 -0
  44. data/spec/test-files/test-5-context.jsonld +7 -0
  45. data/spec/test-files/test-5-expanded.jsonld +9 -0
  46. data/spec/test-files/test-5-input.yamlld +10 -0
  47. data/spec/test-files/test-5-rdf.ttl +7 -0
  48. data/spec/test-files/test-6-compacted.jsonld +10 -0
  49. data/spec/test-files/test-6-context.jsonld +7 -0
  50. data/spec/test-files/test-6-expanded.jsonld +10 -0
  51. data/spec/test-files/test-6-input.yamlld +12 -0
  52. data/spec/test-files/test-6-rdf.ttl +6 -0
  53. data/spec/test-files/test-7-compacted.jsonld +23 -0
  54. data/spec/test-files/test-7-context.jsonld +4 -0
  55. data/spec/test-files/test-7-expanded.jsonld +20 -0
  56. data/spec/test-files/test-7-input.yamlld +16 -0
  57. data/spec/test-files/test-7-rdf.ttl +14 -0
  58. data/spec/test-files/test-8-compacted.jsonld +34 -0
  59. data/spec/test-files/test-8-context.jsonld +11 -0
  60. data/spec/test-files/test-8-expanded.jsonld +24 -0
  61. data/spec/test-files/test-8-frame.jsonld +18 -0
  62. data/spec/test-files/test-8-framed.jsonld +25 -0
  63. data/spec/test-files/test-8-input.yamlld +24 -0
  64. data/spec/test-files/test-8-rdf.ttl +15 -0
  65. data/spec/test-files/test-9-compacted.jsonld +20 -0
  66. data/spec/test-files/test-9-context.jsonld +13 -0
  67. data/spec/test-files/test-9-expanded.jsonld +14 -0
  68. data/spec/test-files/test-9-input.yamlld +16 -0
  69. data/spec/to_rdf_spec.rb +556 -0
  70. data/spec/writer_spec.rb +441 -0
  71. metadata +350 -0
@@ -0,0 +1,441 @@
1
+ # coding: utf-8
2
+ require_relative 'spec_helper'
3
+ require 'rdf/spec/writer'
4
+
5
+ describe YAML_LD::Writer do
6
+ let(:logger) {RDF::Spec.logger}
7
+
8
+ after(:each) {|example| puts logger.to_s if example.exception}
9
+
10
+ it_behaves_like 'an RDF::Writer' do
11
+ let(:writer) {YAML_LD::Writer.new(StringIO.new, logger: logger)}
12
+ end
13
+
14
+ describe ".for" do
15
+ [
16
+ :yamlld,
17
+ "etc/doap.yamlld",
18
+ {file_name: 'etc/doap.yamlld'},
19
+ {file_extension: 'yamlld'},
20
+ {content_type: 'application/ld+yaml'},
21
+ ].each do |arg|
22
+ it "discovers with #{arg.inspect}" do
23
+ expect(RDF::Reader.for(arg)).to eq YAML_LD::Reader
24
+ end
25
+ end
26
+ end
27
+
28
+ context "simple tests" do
29
+ it "should use full URIs without base" do
30
+ input = %(<http://a/b> <http://a/c> <http://a/d> .)
31
+ expect(serialize(input)).to produce_yamlld(%(
32
+ - "@id":
33
+ http://a/b
34
+ http://a/c:
35
+ - "@id":
36
+ http://a/d
37
+ ), logger)
38
+ end
39
+
40
+ it "should use qname URIs with standard prefix" do
41
+ input = %(<http://xmlns.com/foaf/0.1/b> <http://xmlns.com/foaf/0.1/c> <http://xmlns.com/foaf/0.1/d> .)
42
+ expect(serialize(input, standard_prefixes: true)).to produce_yamlld(%(
43
+ "@context":
44
+ foaf: http://xmlns.com/foaf/0.1/
45
+ "@id": foaf:b
46
+ foaf:c:
47
+ "@id": foaf:d
48
+ ), logger)
49
+ end
50
+
51
+ it "should use qname URIs with parsed prefix" do
52
+ input = %(
53
+ <https://senet.org/gm> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://vocab.org/frbr/core#Work> .
54
+ <https://senet.org/gm> <http://purl.org/dc/terms/title> "Rhythm Paradise"@en .
55
+ <https://senet.org/gm> <https://senet.org/ns#unofficialTitle> "Rhythm Tengoku"@en .
56
+ <https://senet.org/gm> <https://senet.org/ns#urlkey> "rhythm-tengoku" .
57
+ )
58
+ expect(serialize(input, prefixes: {
59
+ dc: "http://purl.org/dc/terms/",
60
+ frbr: "http://vocab.org/frbr/core#",
61
+ senet: "https://senet.org/ns#",
62
+ })).to produce_yamlld(%(
63
+ "@context":
64
+ dc: http://purl.org/dc/terms/
65
+ frbr: "http://vocab.org/frbr/core#"
66
+ senet: "https://senet.org/ns#"
67
+ "@id": https://senet.org/gm
68
+ "@type": frbr:Work
69
+ dc:title:
70
+ "@language": en
71
+ "@value": Rhythm Paradise
72
+ senet:unofficialTitle:
73
+ "@language": en
74
+ "@value": Rhythm Tengoku
75
+ senet:urlkey: rhythm-tengoku
76
+ ), logger)
77
+ end
78
+
79
+ it "should use CURIEs with empty prefix" do
80
+ input = %(<http://xmlns.com/foaf/0.1/b> <http://xmlns.com/foaf/0.1/c> <http://xmlns.com/foaf/0.1/d> .)
81
+ begin
82
+ expect(serialize(input, prefixes: { "" => RDF::Vocab::FOAF})).
83
+ to produce_yamlld(%(
84
+ "@context":
85
+ "": http://xmlns.com/foaf/0.1/
86
+ "@id": ":b"
87
+ ":c":
88
+ "@id": ":d"
89
+ ), logger)
90
+ rescue YAML_LD::JsonLdError, YAML_LD::JsonLdError, TypeError => e
91
+ fail("#{e.class}: #{e.message}\n" +
92
+ "#{logger}\n" +
93
+ "Backtrace:\n#{e.backtrace.join("\n")}")
94
+ end
95
+ end
96
+
97
+ it "should not use terms if no suffix" do
98
+ input = %(<http://xmlns.com/foaf/0.1/> <http://xmlns.com/foaf/0.1/> <http://xmlns.com/foaf/0.1/> .)
99
+ expect(serialize(input, standard_prefixes: true)).
100
+ not_to produce_yamlld(%(
101
+ "@context":
102
+ foaf: http://xmlns.com/foaf/0.1/
103
+ "@id": foaf
104
+ foaf:
105
+ "@id": foaf
106
+ ), logger)
107
+ end
108
+
109
+ it "should not use CURIE with illegal local part" do
110
+ input = %(
111
+ @prefix db: <http://dbpedia.org/resource/> .
112
+ @prefix dbo: <http://dbpedia.org/ontology/> .
113
+ db:Michael_Jackson dbo:artistOf <http://dbpedia.org/resource/%28I_Can%27t_Make_It%29_Another_Day> .
114
+ )
115
+
116
+ expect(serialize(input, prefixes: {
117
+ "db" => RDF::URI("http://dbpedia.org/resource/"),
118
+ "dbo" => RDF::URI("http://dbpedia.org/ontology/")})).
119
+ to produce_yamlld(%(
120
+ "@context":
121
+ db: http://dbpedia.org/resource/
122
+ dbo: http://dbpedia.org/ontology/
123
+ "@id": db:Michael_Jackson
124
+ dbo:artistOf:
125
+ "@id": db:%28I_Can%27t_Make_It%29_Another_Day
126
+ ), logger)
127
+ end
128
+
129
+ it "should not use provided node identifiers if :unique_bnodes set" do
130
+ input = %(_:a <http://example.com/foo> _:b \.)
131
+ result = serialize(input, unique_bnodes: true, context: {})
132
+ expect(result.to_yaml).to match(%r(_:g\w+))
133
+ end
134
+
135
+ it "serializes multiple subjects" do
136
+ input = %q(
137
+ @prefix : <http://www.w3.org/2006/03/test-description#> .
138
+ @prefix dc: <http://purl.org/dc/terms/> .
139
+ <http://example.com/test-cases/0001> a :TestCase .
140
+ <http://example.com/test-cases/0002> a :TestCase .
141
+ )
142
+ expect(serialize(input, prefixes: {"" => "http://www.w3.org/2006/03/test-description#"})).
143
+ to produce_yamlld(%(
144
+ "@context":
145
+ "": http://www.w3.org/2006/03/test-description#
146
+ dc: http://purl.org/dc/terms/
147
+ "@graph":
148
+ - "@id": http://example.com/test-cases/0001
149
+ "@type": ":TestCase"
150
+ - "@id": http://example.com/test-cases/0002
151
+ "@type": ":TestCase"
152
+ ), logger)
153
+ end
154
+
155
+ it "serializes Wikia OWL example" do
156
+ input = %q(
157
+ @prefix owl: <http://www.w3.org/2002/07/owl#> .
158
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
159
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
160
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
161
+
162
+ <http://data.wikia.com/terms#Character> a owl:Class;
163
+ rdfs:subClassOf _:a .
164
+ _:a a owl:Restriction;
165
+ owl:minQualifiedCardinality "1"^^xsd:nonNegativeInteger;
166
+ owl:onClass <http://data.wikia.com/terms#Element>;
167
+ owl:onProperty <http://data.wikia.com/terms#characterIn> .
168
+ )
169
+ expect(serialize(input, rename_bnodes: false, prefixes: {
170
+ owl: "http://www.w3.org/2002/07/owl#",
171
+ rdfs: "http://www.w3.org/2000/01/rdf-schema#",
172
+ xsd: "http://www.w3.org/2001/XMLSchema#"
173
+ })).
174
+ to produce_yamlld(%(
175
+ "@context":
176
+ owl: http://www.w3.org/2002/07/owl#
177
+ rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
178
+ rdfs: http://www.w3.org/2000/01/rdf-schema#
179
+ xsd: http://www.w3.org/2001/XMLSchema#
180
+ "@graph":
181
+ - "@id": _:a
182
+ "@type": owl:Restriction
183
+ owl:minQualifiedCardinality:
184
+ "@value": "1"
185
+ "@type": xsd:nonNegativeInteger
186
+ owl:onClass:
187
+ "@id": http://data.wikia.com/terms#Element
188
+ owl:onProperty:
189
+ "@id": http://data.wikia.com/terms#characterIn
190
+ - "@id": http://data.wikia.com/terms#Character
191
+ "@type": owl:Class
192
+ rdfs:subClassOf:
193
+ "@id": _:a
194
+ ), logger)
195
+ end
196
+ end
197
+
198
+ context "RDF-star" do
199
+ {
200
+ "subject-iii": {
201
+ input: RDF::Statement(
202
+ RDF::Statement(
203
+ RDF::URI('http://example/s1'),
204
+ RDF::URI('http://example/p1'),
205
+ RDF::URI('http://example/o1')),
206
+ RDF::URI('http://example/p'),
207
+ RDF::URI('http://example/o')),
208
+ output: %(
209
+ "@context":
210
+ ex: http://example/
211
+ "@id":
212
+ "@id": ex:s1
213
+ ex:p1:
214
+ "@id": ex:o1
215
+ ex:p:
216
+ "@id": ex:o
217
+ )
218
+ },
219
+ "subject-iib": {
220
+ input: RDF::Statement(
221
+ RDF::Statement(
222
+ RDF::URI('http://example/s1'),
223
+ RDF::URI('http://example/p1'),
224
+ RDF::Node.new('o1')),
225
+ RDF::URI('http://example/p'),
226
+ RDF::URI('http://example/o')),
227
+ output: %(
228
+ "@context":
229
+ ex: http://example/
230
+ "@id":
231
+ "@id": ex:s1
232
+ ex:p1:
233
+ "@id": _:o1
234
+ ex:p:
235
+ "@id": ex:o
236
+ )
237
+ },
238
+ "subject-iil": {
239
+ input: RDF::Statement(
240
+ RDF::Statement(
241
+ RDF::URI('http://example/s1'),
242
+ RDF::URI('http://example/p1'),
243
+ RDF::Literal('o1')),
244
+ RDF::URI('http://example/p'),
245
+ RDF::URI('http://example/o')),
246
+ output: %(
247
+ "@context":
248
+ ex: http://example/
249
+ "@id":
250
+ "@id": ex:s1
251
+ ex:p1: o1
252
+ ex:p:
253
+ "@id": ex:o
254
+ )
255
+ },
256
+ "subject-bii": {
257
+ input: RDF::Statement(
258
+ RDF::Statement(
259
+ RDF::Node('s1'),
260
+ RDF::URI('http://example/p1'),
261
+ RDF::URI('http://example/o1')),
262
+ RDF::URI('http://example/p'),
263
+ RDF::URI('http://example/o')),
264
+ output: %(
265
+ "@context":
266
+ ex: http://example/
267
+ "@id":
268
+ "@id": _:s1
269
+ ex:p1:
270
+ "@id": ex:o1
271
+ ex:p:
272
+ "@id": ex:o
273
+ )
274
+ },
275
+ "subject-bib": {
276
+ input: RDF::Statement(
277
+ RDF::Statement(
278
+ RDF::Node('s1'),
279
+ RDF::URI('http://example/p1'),
280
+ RDF::Node.new('o1')),
281
+ RDF::URI('http://example/p'), RDF::URI('http://example/o')),
282
+ output: %(
283
+ "@context":
284
+ ex: http://example/
285
+ "@id":
286
+ "@id": _:s1
287
+ ex:p1:
288
+ "@id": _:o1
289
+ ex:p:
290
+ "@id": ex:o
291
+ )
292
+ },
293
+ "subject-bil": {
294
+ input: RDF::Statement(
295
+ RDF::Statement(
296
+ RDF::Node('s1'),
297
+ RDF::URI('http://example/p1'),
298
+ RDF::Literal('o1')),
299
+ RDF::URI('http://example/p'),
300
+ RDF::URI('http://example/o')),
301
+ output: %(
302
+ "@context":
303
+ ex: http://example/
304
+ "@id":
305
+ "@id": _:s1
306
+ ex:p1: o1
307
+ ex:p:
308
+ "@id": ex:o
309
+ )
310
+ },
311
+ "object-iii": {
312
+ input: RDF::Statement(
313
+ RDF::URI('http://example/s'),
314
+ RDF::URI('http://example/p'),
315
+ RDF::Statement(
316
+ RDF::URI('http://example/s1'),
317
+ RDF::URI('http://example/p1'),
318
+ RDF::URI('http://example/o1'))),
319
+ output: %(
320
+ "@context":
321
+ ex: http://example/
322
+ "@id": ex:s
323
+ ex:p:
324
+ "@id":
325
+ "@id": ex:s1
326
+ ex:p1:
327
+ "@id": ex:o1
328
+ )
329
+ },
330
+ "object-iib": {
331
+ input: RDF::Statement(
332
+ RDF::URI('http://example/s'),
333
+ RDF::URI('http://example/p'),
334
+ RDF::Statement(
335
+ RDF::URI('http://example/s1'),
336
+ RDF::URI('http://example/p1'),
337
+ RDF::Node.new('o1'))),
338
+ output: %(
339
+ "@context":
340
+ ex: http://example/
341
+ "@id": ex:s
342
+ ex:p:
343
+ "@id":
344
+ "@id": ex:s1
345
+ ex:p1:
346
+ "@id": _:o1
347
+ )
348
+ },
349
+ "object-iil": {
350
+ input: RDF::Statement(
351
+ RDF::URI('http://example/s'),
352
+ RDF::URI('http://example/p'),
353
+ RDF::Statement(
354
+ RDF::URI('http://example/s1'),
355
+ RDF::URI('http://example/p1'),
356
+ RDF::Literal('o1'))),
357
+ output: %(
358
+ "@context":
359
+ ex: http://example/
360
+ "@id": ex:s
361
+ ex:p:
362
+ "@id":
363
+ "@id": ex:s1
364
+ ex:p1: o1
365
+ )
366
+ },
367
+ "recursive-subject": {
368
+ input: RDF::Statement(
369
+ RDF::Statement(
370
+ RDF::Statement(
371
+ RDF::URI('http://example/s2'),
372
+ RDF::URI('http://example/p2'),
373
+ RDF::URI('http://example/o2')),
374
+ RDF::URI('http://example/p1'),
375
+ RDF::URI('http://example/o1')),
376
+ RDF::URI('http://example/p'),
377
+ RDF::URI('http://example/o')),
378
+ output: %(
379
+ "@context":
380
+ ex: http://example/
381
+ "@id":
382
+ "@id":
383
+ "@id": ex:s2
384
+ ex:p2:
385
+ "@id": ex:o2
386
+ ex:p1:
387
+ "@id": ex:o1
388
+ ex:p:
389
+ "@id": ex:o
390
+ )
391
+ },
392
+ }.each do |name, params|
393
+ it name do
394
+ graph = RDF::Graph.new {|g| g << params[:input]}
395
+ expect(
396
+ serialize(graph, rdfstar: true, prefixes: {ex: 'http://example/'})
397
+ ).to produce_yamlld(params[:output], logger)
398
+ end
399
+ end
400
+ end
401
+
402
+ #context "Writes fromRdf tests to isomorphic graph" do
403
+ # require 'suite_helper'
404
+ # m = Fixtures::SuiteTest::Manifest.open("#{Fixtures::SuiteTest::SUITE}fromRdf-manifest.jsonld")
405
+ # describe m.name do
406
+ # m.entries.each do |t|
407
+ # next unless t.positiveTest? && !t.property('input').include?('0016')
408
+ # specify "#{t.property('@id')}: #{t.name}" do
409
+ # logger.info "test: #{t.inspect}"
410
+ # logger.info "source: #{t.input}"
411
+ # t.logger = logger
412
+ # pending "Shared list BNode in different graphs" if t.property('input').include?("fromRdf-0021")
413
+ # repo = RDF::Repository.load(t.input_loc, format: :nquads)
414
+ # jsonld = YAML_LD::Writer.buffer(logger: t.logger, **t.options) do |writer|
415
+ # writer << repo
416
+ # end
417
+ #
418
+ # # And then, re-generate jsonld as RDF
419
+ #
420
+ # expect(parse(jsonld, format: :jsonld, **t.options)).to be_equivalent_graph(repo, t)
421
+ # end
422
+ # end
423
+ # end
424
+ #end unless ENV['CI']
425
+
426
+ def parse(input, format: :trig, **options)
427
+ reader = RDF::Reader.for(format)
428
+ RDF::Repository.new << reader.new(input, **options)
429
+ end
430
+
431
+ # Serialize ntstr to a string and compare against regexps
432
+ def serialize(ntstr, **options)
433
+ g = ntstr.is_a?(String) ? parse(ntstr, **options) : ntstr
434
+ #logger.info g.dump(:ttl)
435
+ result = YAML_LD::Writer.buffer(logger: logger, **options) do |writer|
436
+ writer << g
437
+ end
438
+
439
+ Psych.safe_load(result, aliases: true)
440
+ end
441
+ end