json-ld 2.2.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.md +55 -55
- data/VERSION +1 -1
- data/lib/json/ld.rb +4 -2
- data/lib/json/ld/api.rb +49 -59
- data/lib/json/ld/compact.rb +60 -56
- data/lib/json/ld/context.rb +52 -40
- data/lib/json/ld/expand.rb +53 -61
- data/lib/json/ld/extensions.rb +31 -16
- data/lib/json/ld/flatten.rb +99 -90
- data/lib/json/ld/format.rb +2 -2
- data/lib/json/ld/frame.rb +47 -30
- data/lib/json/ld/from_rdf.rb +31 -23
- data/lib/json/ld/resource.rb +1 -1
- data/lib/json/ld/to_rdf.rb +4 -2
- data/lib/json/ld/utils.rb +25 -35
- data/lib/json/ld/writer.rb +25 -1
- data/spec/api_spec.rb +1 -0
- data/spec/compact_spec.rb +536 -31
- data/spec/context_spec.rb +109 -43
- data/spec/expand_spec.rb +413 -18
- data/spec/flatten_spec.rb +107 -27
- data/spec/frame_spec.rb +255 -34
- data/spec/from_rdf_spec.rb +102 -3
- data/spec/streaming_writer_spec.rb +8 -9
- data/spec/suite_compact_spec.rb +2 -2
- data/spec/suite_expand_spec.rb +2 -2
- data/spec/suite_flatten_spec.rb +2 -2
- data/spec/suite_frame_spec.rb +2 -2
- data/spec/suite_from_rdf_spec.rb +2 -3
- data/spec/suite_helper.rb +57 -61
- data/spec/suite_remote_doc_spec.rb +2 -2
- data/spec/suite_to_rdf_spec.rb +4 -4
- data/spec/to_rdf_spec.rb +88 -1
- data/spec/writer_spec.rb +5 -6
- metadata +5 -7
- data/spec/suite_error_spec.rb +0 -16
data/lib/json/ld/from_rdf.rb
CHANGED
@@ -10,23 +10,23 @@ module JSON::LD
|
|
10
10
|
# Generate a JSON-LD array representation from an array of `RDF::Statement`.
|
11
11
|
# Representation is in expanded form
|
12
12
|
#
|
13
|
-
# @param [Array<RDF::Statement>, RDF::Enumerable]
|
13
|
+
# @param [Array<RDF::Statement>, RDF::Enumerable] dataset
|
14
14
|
# @param [Boolean] useRdfType (false)
|
15
15
|
# If set to `true`, the JSON-LD processor will treat `rdf:type` like a normal property instead of using `@type`.
|
16
16
|
# @param [Boolean] useNativeTypes (false) use native representations
|
17
17
|
# @return [Array<Hash>] the JSON-LD document in normalized form
|
18
|
-
def from_statements(
|
18
|
+
def from_statements(dataset, useRdfType: false, useNativeTypes: false)
|
19
19
|
default_graph = {}
|
20
20
|
graph_map = {'@default' => default_graph}
|
21
|
-
|
21
|
+
referenced_once = {}
|
22
22
|
|
23
23
|
value = nil
|
24
24
|
ec = Context.new
|
25
25
|
|
26
26
|
# Create a map for node to object representation
|
27
27
|
|
28
|
-
# For each
|
29
|
-
|
28
|
+
# For each statement in dataset
|
29
|
+
dataset.each do |statement|
|
30
30
|
#log_debug("statement") { statement.to_nquads.chomp}
|
31
31
|
|
32
32
|
name = statement.graph_name ? ec.expand_iri(statement.graph_name).to_s : '@default'
|
@@ -53,16 +53,23 @@ module JSON::LD
|
|
53
53
|
|
54
54
|
merge_value(node, statement.predicate.to_s, value)
|
55
55
|
|
56
|
-
# If object is a blank node identifier or
|
57
|
-
if statement.object.
|
56
|
+
# If object is a blank node identifier or rdf:nil, it might represent the a list node:
|
57
|
+
if statement.object == RDF.nil
|
58
58
|
# Append a new JSON object consisting of three members, node, property, and value to the usages array. The node member is set to a reference to node, property to predicate, and value to a reference to value.
|
59
|
-
|
59
|
+
object = node_map[statement.object.to_s]
|
60
|
+
merge_value(object, :usages, {
|
60
61
|
node: node,
|
61
62
|
property: statement.predicate.to_s,
|
62
63
|
value: value
|
63
64
|
})
|
64
|
-
|
65
|
-
|
65
|
+
elsif referenced_once.has_key?(statement.object.to_s)
|
66
|
+
referenced_once[statement.object.to_s] = false
|
67
|
+
elsif statement.object.node?
|
68
|
+
referenced_once[statement.object.to_s] = {
|
69
|
+
node: node,
|
70
|
+
property: statement.predicate.to_s,
|
71
|
+
value: value
|
72
|
+
}
|
66
73
|
end
|
67
74
|
end
|
68
75
|
|
@@ -78,30 +85,31 @@ module JSON::LD
|
|
78
85
|
# If property equals rdf:rest, the value associated to the usages member of node has exactly 1 entry, node has a rdf:first and rdf:rest property, both of which have as value an array consisting of a single element, and node has no other members apart from an optional @type member whose value is an array with a single item equal to rdf:List, node represents a well-formed list node. Continue with the following steps:
|
79
86
|
#log_debug("list element?") {node.to_json(JSON_STATE) rescue 'malformed json'}
|
80
87
|
while property == RDF.rest.to_s &&
|
81
|
-
Array(node_usages_map[node['@id']]).uniq.length == 1 &&
|
82
88
|
blank_node?(node) &&
|
89
|
+
referenced_once[node['@id']] &&
|
83
90
|
node.keys.none? {|k| !["@id", '@type', :usages, RDF.first.to_s, RDF.rest.to_s].include?(k)} &&
|
84
|
-
Array(node[:usages]).length == 1 &&
|
85
91
|
(f = node[RDF.first.to_s]).is_a?(Array) && f.length == 1 &&
|
86
92
|
(r = node[RDF.rest.to_s]).is_a?(Array) && r.length == 1 &&
|
87
93
|
((t = node['@type']).nil? || t == [RDF.List.to_s])
|
88
94
|
list << Array(node[RDF.first.to_s]).first
|
89
95
|
list_nodes << node['@id']
|
90
|
-
|
96
|
+
|
97
|
+
# get next node, moving backwards through list
|
98
|
+
node_usage = referenced_once[node['@id']]
|
91
99
|
node, property, head = node_usage[:node], node_usage[:property], node_usage[:value]
|
92
100
|
end
|
93
101
|
|
94
102
|
# If property equals rdf:first, i.e., the detected list is nested inside another list
|
95
|
-
if property == RDF.first.to_s
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
end
|
103
|
+
#if property == RDF.first.to_s
|
104
|
+
# # and the value of the @id of node equals rdf:nil, i.e., the detected list is empty, continue with the next usage item. The rdf:nil node cannot be converted to a list object as it would result in a list of lists, which isn't supported.
|
105
|
+
# next if node['@id'] == RDF.nil.to_s
|
106
|
+
#
|
107
|
+
# # Otherwise, the list consists of at least one item. We preserve the head node and transform the rest of the linked list to a list object
|
108
|
+
# head_id = head['@id']
|
109
|
+
# head = graph_object[head_id]
|
110
|
+
# head = Array(head[RDF.rest.to_s]).first
|
111
|
+
# list.pop; list_nodes.pop
|
112
|
+
#end
|
105
113
|
|
106
114
|
head.delete('@id')
|
107
115
|
head['@list'] = list.reverse
|
data/lib/json/ld/resource.rb
CHANGED
@@ -76,7 +76,7 @@ module JSON::LD
|
|
76
76
|
# @option options [Boolean] :stub (false)
|
77
77
|
# This is a stand-in for another resource that has
|
78
78
|
# not yet been retrieved (or created) from Mongo
|
79
|
-
def initialize(node_definition, options
|
79
|
+
def initialize(node_definition, **options)
|
80
80
|
@context = options[:context]
|
81
81
|
@clean = options.fetch(:clean, false)
|
82
82
|
@new = options.fetch(:new, true)
|
data/lib/json/ld/to_rdf.rb
CHANGED
@@ -37,6 +37,9 @@ module JSON::LD
|
|
37
37
|
# Initialize literal as an RDF literal using value and datatype. If element has the key @language and datatype is xsd:string, then add the value associated with the @language key as the language of the object.
|
38
38
|
language = item.fetch('@language', nil)
|
39
39
|
return RDF::Literal.new(value, datatype: datatype, language: language)
|
40
|
+
elsif list?(item)
|
41
|
+
# If item is a list object, initialize list_results as an empty array, and object to the result of the List Conversion algorithm, passing the value associated with the @list key from item and list_results.
|
42
|
+
return parse_list(item['@list'], graph_name: graph_name, &block)
|
40
43
|
end
|
41
44
|
|
42
45
|
subject = item['@id'] ? as_resource(item['@id']) : node
|
@@ -64,8 +67,7 @@ module JSON::LD
|
|
64
67
|
vv.each do |v|
|
65
68
|
if list?(v)
|
66
69
|
#log_debug("item_to_rdf") {"list: #{v.inspect}"}
|
67
|
-
|
68
|
-
object = parse_list(v['@list'], graph_name: graph_name, &block)
|
70
|
+
object = item_to_rdf(v, graph_name: graph_name, &block)
|
69
71
|
|
70
72
|
# Append a triple composed of object, prediate, and object to results and add all triples from list_results to results.
|
71
73
|
yield RDF::Statement(object, predicate, subject, graph_name: graph_name)
|
data/lib/json/ld/utils.rb
CHANGED
@@ -110,6 +110,14 @@ module JSON::LD
|
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
|
+
##
|
114
|
+
# Represent as an array
|
115
|
+
# @param [Object] object
|
116
|
+
# @return [Array<Object>]
|
117
|
+
def as_array(object)
|
118
|
+
object.is_a?(Array) ? object : [object]
|
119
|
+
end
|
120
|
+
|
113
121
|
##
|
114
122
|
# Compares two JSON-LD values for equality. Two JSON-LD values will be
|
115
123
|
# considered equal if:
|
@@ -142,30 +150,33 @@ module JSON::LD
|
|
142
150
|
# @param [Hash] subject the hash to add the value to.
|
143
151
|
# @param [String] property the property that relates the value to the subject.
|
144
152
|
# @param [Object] value the value to add.
|
145
|
-
# @param [
|
146
|
-
#
|
147
|
-
#
|
148
|
-
# an array
|
149
|
-
# @
|
153
|
+
# @param [Boolean] property_is_array (false)
|
154
|
+
# true if the property is always an array, false if not.
|
155
|
+
# @param [Boolean] value_is_array (false)
|
156
|
+
# true if the value to be added should be preserved as an array (lists)
|
157
|
+
# @param [Boolean] allow_duplicate (true)
|
150
158
|
# true to allow duplicates, false not to (uses
|
151
159
|
# a simple shallow comparison of subject ID or value).
|
152
|
-
def add_value(subject, property, value,
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
subject[property] = [] if value.empty? &&
|
157
|
-
value.each
|
160
|
+
def add_value(subject, property, value, property_is_array: false, value_is_array: false, allow_duplicate: true)
|
161
|
+
if value_is_array
|
162
|
+
subject[property] = value
|
163
|
+
elsif value.is_a?(Array)
|
164
|
+
subject[property] = [] if value.empty? && property_is_array
|
165
|
+
value.each do |v|
|
166
|
+
add_value(subject, property, v,
|
167
|
+
property_is_array: property_is_array, allow_duplicate: allow_duplicate)
|
168
|
+
end
|
158
169
|
elsif subject[property]
|
159
170
|
# check if subject already has value if duplicates not allowed
|
160
|
-
_has_value = !
|
171
|
+
_has_value = !allow_duplicate && has_value(subject, property, value)
|
161
172
|
|
162
173
|
# make property an array if value not present or always an array
|
163
|
-
if !subject[property].is_a?(Array) && (!_has_value ||
|
174
|
+
if !subject[property].is_a?(Array) && (!_has_value || property_is_array)
|
164
175
|
subject[property] = [subject[property]]
|
165
176
|
end
|
166
177
|
subject[property] << value unless _has_value
|
167
178
|
else
|
168
|
-
subject[property] =
|
179
|
+
subject[property] = property_is_array ? [value] : value
|
169
180
|
end
|
170
181
|
end
|
171
182
|
|
@@ -219,27 +230,6 @@ module JSON::LD
|
|
219
230
|
values << value
|
220
231
|
end
|
221
232
|
end
|
222
|
-
|
223
|
-
# Merge values into compacted results, creating arrays if necessary
|
224
|
-
def merge_compacted_value(hash, key, value)
|
225
|
-
return unless hash
|
226
|
-
case hash[key]
|
227
|
-
when nil then hash[key] = value
|
228
|
-
when Array
|
229
|
-
if value.is_a?(Array)
|
230
|
-
hash[key].concat(value)
|
231
|
-
else
|
232
|
-
hash[key] << value
|
233
|
-
end
|
234
|
-
else
|
235
|
-
hash[key] = [hash[key]]
|
236
|
-
if value.is_a?(Array)
|
237
|
-
hash[key].concat(value)
|
238
|
-
else
|
239
|
-
hash[key] << value
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
243
233
|
end
|
244
234
|
|
245
235
|
##
|
data/lib/json/ld/writer.rb
CHANGED
@@ -90,12 +90,36 @@ module JSON::LD
|
|
90
90
|
control: :url2,
|
91
91
|
on: ["--context CONTEXT"],
|
92
92
|
description: "Context to use when compacting.") {|arg| RDF::URI(arg)},
|
93
|
+
RDF::CLI::Option.new(
|
94
|
+
symbol: :embed,
|
95
|
+
datatype: %w(@always @last @never),
|
96
|
+
control: :select,
|
97
|
+
on: ["--embed EMBED"],
|
98
|
+
description: "How to embed matched objects (@last).") {|arg| RDF::URI(arg)},
|
99
|
+
RDF::CLI::Option.new(
|
100
|
+
symbol: :explicit,
|
101
|
+
datatype: TrueClass,
|
102
|
+
control: :checkbox,
|
103
|
+
on: ["--explicit"],
|
104
|
+
description: "Only include explicitly declared properties in output (false)") {|arg| RDF::URI(arg)},
|
105
|
+
RDF::CLI::Option.new(
|
106
|
+
symbol: :omitDefault,
|
107
|
+
datatype: TrueClass,
|
108
|
+
control: :checkbox,
|
109
|
+
on: ["--omitDefault"],
|
110
|
+
description: "Omit missing properties from output (false)") {|arg| RDF::URI(arg)},
|
93
111
|
RDF::CLI::Option.new(
|
94
112
|
symbol: :processing_mode,
|
95
113
|
datatype: %w(json-ld-1.0 json-ld-1.1),
|
96
114
|
control: :radio,
|
97
115
|
on: ["--processingMode MODE", %w(json-ld-1.0 json-ld-1.1)],
|
98
116
|
description: "Set Processing Mode (json-ld-1.0 or json-ld-1.1)"),
|
117
|
+
RDF::CLI::Option.new(
|
118
|
+
symbol: :requireAll,
|
119
|
+
datatype: TrueClass,
|
120
|
+
control: :checkbox,
|
121
|
+
on: ["--requireAll"],
|
122
|
+
description: "Require all properties to match (true)") {|arg| RDF::URI(arg)},
|
99
123
|
RDF::CLI::Option.new(
|
100
124
|
symbol: :stream,
|
101
125
|
datatype: TrueClass,
|
@@ -139,7 +163,7 @@ module JSON::LD
|
|
139
163
|
# @yieldreturn [void]
|
140
164
|
# @yield [writer]
|
141
165
|
# @yieldparam [RDF::Writer] writer
|
142
|
-
def initialize(output = $stdout, options
|
166
|
+
def initialize(output = $stdout, **options, &block)
|
143
167
|
options[:base_uri] ||= options[:base] if options.has_key?(:base)
|
144
168
|
options[:base] ||= options[:base_uri] if options.has_key?(:base_uri)
|
145
169
|
super do
|
data/spec/api_spec.rb
CHANGED
data/spec/compact_spec.rb
CHANGED
@@ -292,7 +292,47 @@ describe JSON::LD::API do
|
|
292
292
|
},
|
293
293
|
"http://example.org/vocab#contains": "this-is-not-an-IRI"
|
294
294
|
})
|
295
|
-
}
|
295
|
+
},
|
296
|
+
"Language map term with language value" => {
|
297
|
+
input: %([{"http://example/t": {"@value": "foo", "@language": "en"}}]),
|
298
|
+
context: %({"t": {"@id": "http://example/t", "@container": "@language"}}),
|
299
|
+
output: %({
|
300
|
+
"@context": {
|
301
|
+
"t": {"@id": "http://example/t", "@container": "@language"}
|
302
|
+
},
|
303
|
+
"t": {"en": "foo"}
|
304
|
+
})
|
305
|
+
},
|
306
|
+
"Datatyped term with datatyped value" => {
|
307
|
+
input: %([{"http://example/t": {"@value": "foo", "@type": "http:/example/type"}}]),
|
308
|
+
context: %({"t": {"@id": "http://example/t", "@type": "http:/example/type"}}),
|
309
|
+
output: %({
|
310
|
+
"@context": {
|
311
|
+
"t": {"@id": "http://example/t", "@type": "http:/example/type"}
|
312
|
+
},
|
313
|
+
"t": "foo"
|
314
|
+
})
|
315
|
+
},
|
316
|
+
"Datatyped term with simple value" => {
|
317
|
+
input: %([{"http://example/t": {"@value": "foo"}}]),
|
318
|
+
context: %({"t": {"@id": "http://example/t", "@type": "http:/example/type"}}),
|
319
|
+
output: %({
|
320
|
+
"@context": {
|
321
|
+
"t": {"@id": "http://example/t", "@type": "http:/example/type"}
|
322
|
+
},
|
323
|
+
"http://example/t": "foo"
|
324
|
+
})
|
325
|
+
},
|
326
|
+
"Datatyped term with object value" => {
|
327
|
+
input: %([{"http://example/t": {"@id": "http://example/id"}}]),
|
328
|
+
context: %({"t": {"@id": "http://example/t", "@type": "http:/example/type"}}),
|
329
|
+
output: %({
|
330
|
+
"@context": {
|
331
|
+
"t": {"@id": "http://example/t", "@type": "http:/example/type"}
|
332
|
+
},
|
333
|
+
"http://example/t": {"@id": "http://example/id"}
|
334
|
+
})
|
335
|
+
},
|
296
336
|
}.each_pair do |title, params|
|
297
337
|
it(title) {run_compact(params)}
|
298
338
|
end
|
@@ -487,6 +527,72 @@ describe JSON::LD::API do
|
|
487
527
|
"foo_de": ["de"]
|
488
528
|
})
|
489
529
|
},
|
530
|
+
"coerced @list containing an empty list" => {
|
531
|
+
input: %([{
|
532
|
+
"http://example.com/foo": [{"@list": [{"@list": []}]}]
|
533
|
+
}]),
|
534
|
+
context: %({
|
535
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
536
|
+
}),
|
537
|
+
output: %({
|
538
|
+
"@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
|
539
|
+
"foo": [[]]
|
540
|
+
}),
|
541
|
+
},
|
542
|
+
"coerced @list containing a list" => {
|
543
|
+
input: %([{
|
544
|
+
"http://example.com/foo": [{"@list": [{"@list": [{"@value": "baz"}]}]}]
|
545
|
+
}]),
|
546
|
+
context: %({
|
547
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
548
|
+
}),
|
549
|
+
output: %({
|
550
|
+
"@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
|
551
|
+
"foo": [["baz"]]
|
552
|
+
}),
|
553
|
+
},
|
554
|
+
"coerced @list containing an deep list" => {
|
555
|
+
input: %([{
|
556
|
+
"http://example.com/foo": [{"@list": [{"@list": [{"@list": [{"@value": "baz"}]}]}]}]
|
557
|
+
}]),
|
558
|
+
context: %({
|
559
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
560
|
+
}),
|
561
|
+
output: %({
|
562
|
+
"@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
|
563
|
+
"foo": [[["baz"]]]
|
564
|
+
}),
|
565
|
+
},
|
566
|
+
"coerced @list containing multiple lists" => {
|
567
|
+
input: %([{
|
568
|
+
"http://example.com/foo": [{"@list": [
|
569
|
+
{"@list": [{"@value": "a"}]},
|
570
|
+
{"@list": [{"@value": "b"}]}
|
571
|
+
]}]
|
572
|
+
}]),
|
573
|
+
context: %({
|
574
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
575
|
+
}),
|
576
|
+
output: %({
|
577
|
+
"@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
|
578
|
+
"foo": [["a"], ["b"]]
|
579
|
+
}),
|
580
|
+
},
|
581
|
+
"coerced @list containing mixed list values" => {
|
582
|
+
input: %([{
|
583
|
+
"http://example.com/foo": [{"@list": [
|
584
|
+
{"@list": [{"@value": "a"}]},
|
585
|
+
{"@value": "b"}
|
586
|
+
]}]
|
587
|
+
}]),
|
588
|
+
context: %({
|
589
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
590
|
+
}),
|
591
|
+
output: %({
|
592
|
+
"@context": {"foo": {"@id": "http://example.com/foo", "@container": "@list"}},
|
593
|
+
"foo": [["a"], "b"]
|
594
|
+
}),
|
595
|
+
},
|
490
596
|
}.each_pair do |title, params|
|
491
597
|
it(title) {run_compact(params)}
|
492
598
|
end
|
@@ -526,6 +632,96 @@ describe JSON::LD::API do
|
|
526
632
|
}
|
527
633
|
})
|
528
634
|
},
|
635
|
+
"simple map with @none node definition" => {
|
636
|
+
input: %([{
|
637
|
+
"@id": "http://example.com/article",
|
638
|
+
"http://example.com/vocab/author": [{
|
639
|
+
"@id": "http://example.org/person/1",
|
640
|
+
"@index": "regular"
|
641
|
+
}, {
|
642
|
+
"@id": "http://example.org/guest/cd24f329aa"
|
643
|
+
}]
|
644
|
+
}]),
|
645
|
+
context: %({
|
646
|
+
"author": {"@id": "http://example.com/vocab/author", "@container": "@index" }
|
647
|
+
}),
|
648
|
+
output: %({
|
649
|
+
"@context": {
|
650
|
+
"author": {
|
651
|
+
"@id": "http://example.com/vocab/author",
|
652
|
+
"@container": "@index"
|
653
|
+
}
|
654
|
+
},
|
655
|
+
"@id": "http://example.com/article",
|
656
|
+
"author": {
|
657
|
+
"regular": {
|
658
|
+
"@id": "http://example.org/person/1"
|
659
|
+
},
|
660
|
+
"@none": {
|
661
|
+
"@id": "http://example.org/guest/cd24f329aa"
|
662
|
+
}
|
663
|
+
}
|
664
|
+
}),
|
665
|
+
processingMode: 'json-ld-1.1'
|
666
|
+
},
|
667
|
+
"simple map with @none value" => {
|
668
|
+
input: %([{
|
669
|
+
"@id": "http://example.com/article",
|
670
|
+
"http://example.com/vocab/author": [{
|
671
|
+
"@value": "Gregg",
|
672
|
+
"@index": "regular"
|
673
|
+
}, {
|
674
|
+
"@value": "Manu"
|
675
|
+
}]
|
676
|
+
}]),
|
677
|
+
context: %({
|
678
|
+
"author": {"@id": "http://example.com/vocab/author", "@container": "@index" }
|
679
|
+
}),
|
680
|
+
output: %({
|
681
|
+
"@context": {
|
682
|
+
"author": {
|
683
|
+
"@id": "http://example.com/vocab/author",
|
684
|
+
"@container": "@index"
|
685
|
+
}
|
686
|
+
},
|
687
|
+
"@id": "http://example.com/article",
|
688
|
+
"author": {
|
689
|
+
"regular": "Gregg",
|
690
|
+
"@none": "Manu"
|
691
|
+
}
|
692
|
+
}),
|
693
|
+
processingMode: 'json-ld-1.1'
|
694
|
+
},
|
695
|
+
"simple map with @none value using alias of @none" => {
|
696
|
+
input: %([{
|
697
|
+
"@id": "http://example.com/article",
|
698
|
+
"http://example.com/vocab/author": [{
|
699
|
+
"@value": "Gregg",
|
700
|
+
"@index": "regular"
|
701
|
+
}, {
|
702
|
+
"@value": "Manu"
|
703
|
+
}]
|
704
|
+
}]),
|
705
|
+
context: %({
|
706
|
+
"author": {"@id": "http://example.com/vocab/author", "@container": "@index" },
|
707
|
+
"none": "@none"
|
708
|
+
}),
|
709
|
+
output: %({
|
710
|
+
"@context": {
|
711
|
+
"author": {
|
712
|
+
"@id": "http://example.com/vocab/author",
|
713
|
+
"@container": "@index"
|
714
|
+
},
|
715
|
+
"none": "@none"
|
716
|
+
},
|
717
|
+
"@id": "http://example.com/article",
|
718
|
+
"author": {
|
719
|
+
"regular": "Gregg",
|
720
|
+
"none": "Manu"
|
721
|
+
}
|
722
|
+
}),
|
723
|
+
processingMode: 'json-ld-1.1'
|
724
|
+
},
|
529
725
|
}.each_pair do |title, params|
|
530
726
|
it(title) {run_compact(params)}
|
531
727
|
end
|
@@ -560,6 +756,66 @@ describe JSON::LD::API do
|
|
560
756
|
}
|
561
757
|
})
|
562
758
|
},
|
759
|
+
"with no @language" => {
|
760
|
+
input: %([
|
761
|
+
{
|
762
|
+
"@id": "http://example.com/queen",
|
763
|
+
"http://example.com/vocab/label": [
|
764
|
+
{"@value": "The Queen", "@language": "en"},
|
765
|
+
{"@value": "Die Königin", "@language": "de"},
|
766
|
+
{"@value": "Ihre Majestät"}
|
767
|
+
]
|
768
|
+
}
|
769
|
+
]),
|
770
|
+
context: %({
|
771
|
+
"vocab": "http://example.com/vocab/",
|
772
|
+
"label": {"@id": "vocab:label", "@container": "@language"}
|
773
|
+
}),
|
774
|
+
output: %({
|
775
|
+
"@context": {
|
776
|
+
"vocab": "http://example.com/vocab/",
|
777
|
+
"label": {"@id": "vocab:label", "@container": "@language"}
|
778
|
+
},
|
779
|
+
"@id": "http://example.com/queen",
|
780
|
+
"label": {
|
781
|
+
"en": "The Queen",
|
782
|
+
"de": "Die Königin",
|
783
|
+
"@none": "Ihre Majestät"
|
784
|
+
}
|
785
|
+
}),
|
786
|
+
processingMode: "json-ld-1.1"
|
787
|
+
},
|
788
|
+
"with no @language using alias of @none" => {
|
789
|
+
input: %([
|
790
|
+
{
|
791
|
+
"@id": "http://example.com/queen",
|
792
|
+
"http://example.com/vocab/label": [
|
793
|
+
{"@value": "The Queen", "@language": "en"},
|
794
|
+
{"@value": "Die Königin", "@language": "de"},
|
795
|
+
{"@value": "Ihre Majestät"}
|
796
|
+
]
|
797
|
+
}
|
798
|
+
]),
|
799
|
+
context: %({
|
800
|
+
"vocab": "http://example.com/vocab/",
|
801
|
+
"label": {"@id": "vocab:label", "@container": "@language"},
|
802
|
+
"none": "@none"
|
803
|
+
}),
|
804
|
+
output: %({
|
805
|
+
"@context": {
|
806
|
+
"vocab": "http://example.com/vocab/",
|
807
|
+
"label": {"@id": "vocab:label", "@container": "@language"},
|
808
|
+
"none": "@none"
|
809
|
+
},
|
810
|
+
"@id": "http://example.com/queen",
|
811
|
+
"label": {
|
812
|
+
"en": "The Queen",
|
813
|
+
"de": "Die Königin",
|
814
|
+
"none": "Ihre Majestät"
|
815
|
+
}
|
816
|
+
}),
|
817
|
+
processingMode: "json-ld-1.1"
|
818
|
+
},
|
563
819
|
}.each_pair do |title, params|
|
564
820
|
it(title) {run_compact(params)}
|
565
821
|
end
|
@@ -633,6 +889,52 @@ describe JSON::LD::API do
|
|
633
889
|
}
|
634
890
|
})
|
635
891
|
},
|
892
|
+
"Indexes using @none" => {
|
893
|
+
input: %([{
|
894
|
+
"http://example/idmap": [
|
895
|
+
{"http://example/label": [{"@value": "Object with no @id"}]}
|
896
|
+
]
|
897
|
+
}]),
|
898
|
+
context: %({
|
899
|
+
"@vocab": "http://example/",
|
900
|
+
"ex": "http://example.org/",
|
901
|
+
"idmap": {"@container": "@id"}
|
902
|
+
}),
|
903
|
+
output: %({
|
904
|
+
"@context": {
|
905
|
+
"@vocab": "http://example/",
|
906
|
+
"ex": "http://example.org/",
|
907
|
+
"idmap": {"@container": "@id"}
|
908
|
+
},
|
909
|
+
"idmap": {
|
910
|
+
"@none": {"label": "Object with no @id"}
|
911
|
+
}
|
912
|
+
})
|
913
|
+
},
|
914
|
+
"Indexes using @none with alias" => {
|
915
|
+
input: %([{
|
916
|
+
"http://example/idmap": [
|
917
|
+
{"http://example/label": [{"@value": "Object with no @id"}]}
|
918
|
+
]
|
919
|
+
}]),
|
920
|
+
context: %({
|
921
|
+
"@vocab": "http://example/",
|
922
|
+
"ex": "http://example.org/",
|
923
|
+
"idmap": {"@container": "@id"},
|
924
|
+
"none": "@none"
|
925
|
+
}),
|
926
|
+
output: %({
|
927
|
+
"@context": {
|
928
|
+
"@vocab": "http://example/",
|
929
|
+
"ex": "http://example.org/",
|
930
|
+
"idmap": {"@container": "@id"},
|
931
|
+
"none": "@none"
|
932
|
+
},
|
933
|
+
"idmap": {
|
934
|
+
"none": {"label": "Object with no @id"}
|
935
|
+
}
|
936
|
+
})
|
937
|
+
},
|
636
938
|
}.each_pair do |title, params|
|
637
939
|
it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))}
|
638
940
|
end
|
@@ -738,6 +1040,52 @@ describe JSON::LD::API do
|
|
738
1040
|
}
|
739
1041
|
})
|
740
1042
|
},
|
1043
|
+
"Indexes using @none" => {
|
1044
|
+
input: %([{
|
1045
|
+
"http://example/typemap": [
|
1046
|
+
{"http://example/label": [{"@value": "Object with no @type"}]}
|
1047
|
+
]
|
1048
|
+
}]),
|
1049
|
+
context: %({
|
1050
|
+
"@vocab": "http://example/",
|
1051
|
+
"ex": "http://example.org/",
|
1052
|
+
"typemap": {"@container": "@type"}
|
1053
|
+
}),
|
1054
|
+
output: %({
|
1055
|
+
"@context": {
|
1056
|
+
"@vocab": "http://example/",
|
1057
|
+
"ex": "http://example.org/",
|
1058
|
+
"typemap": {"@container": "@type"}
|
1059
|
+
},
|
1060
|
+
"typemap": {
|
1061
|
+
"@none": {"label": "Object with no @type"}
|
1062
|
+
}
|
1063
|
+
})
|
1064
|
+
},
|
1065
|
+
"Indexes using @none with alias" => {
|
1066
|
+
input: %([{
|
1067
|
+
"http://example/typemap": [
|
1068
|
+
{"http://example/label": [{"@value": "Object with no @id"}]}
|
1069
|
+
]
|
1070
|
+
}]),
|
1071
|
+
context: %({
|
1072
|
+
"@vocab": "http://example/",
|
1073
|
+
"ex": "http://example.org/",
|
1074
|
+
"typemap": {"@container": "@type"},
|
1075
|
+
"none": "@none"
|
1076
|
+
}),
|
1077
|
+
output: %({
|
1078
|
+
"@context": {
|
1079
|
+
"@vocab": "http://example/",
|
1080
|
+
"ex": "http://example.org/",
|
1081
|
+
"typemap": {"@container": "@type"},
|
1082
|
+
"none": "@none"
|
1083
|
+
},
|
1084
|
+
"typemap": {
|
1085
|
+
"none": {"label": "Object with no @id"}
|
1086
|
+
}
|
1087
|
+
})
|
1088
|
+
},
|
741
1089
|
}.each_pair do |title, params|
|
742
1090
|
it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))}
|
743
1091
|
end
|
@@ -832,10 +1180,57 @@ describe JSON::LD::API do
|
|
832
1180
|
},
|
833
1181
|
"input": {
|
834
1182
|
"@id": "http://example.org/id",
|
835
|
-
"@graph":
|
1183
|
+
"@graph": {"value": "x"}
|
836
1184
|
}
|
837
1185
|
})
|
838
1186
|
},
|
1187
|
+
"Odd framing test" => {
|
1188
|
+
input: %([
|
1189
|
+
{
|
1190
|
+
"http://example.org/claim": [
|
1191
|
+
{
|
1192
|
+
"@graph": [
|
1193
|
+
{
|
1194
|
+
"@id": "http://example.org/1",
|
1195
|
+
"https://example.com#test": [
|
1196
|
+
{
|
1197
|
+
"@value": "foo"
|
1198
|
+
}
|
1199
|
+
]
|
1200
|
+
}
|
1201
|
+
]
|
1202
|
+
}
|
1203
|
+
]
|
1204
|
+
}
|
1205
|
+
]
|
1206
|
+
),
|
1207
|
+
context: %( {
|
1208
|
+
"@version": 1.1,
|
1209
|
+
"@vocab": "https://example.com#",
|
1210
|
+
"ex": "http://example.org/",
|
1211
|
+
"claim": {
|
1212
|
+
"@id": "ex:claim",
|
1213
|
+
"@container": "@graph"
|
1214
|
+
},
|
1215
|
+
"id": "@id"
|
1216
|
+
}),
|
1217
|
+
output: %({
|
1218
|
+
"@context": {
|
1219
|
+
"@version": 1.1,
|
1220
|
+
"@vocab": "https://example.com#",
|
1221
|
+
"ex": "http://example.org/",
|
1222
|
+
"claim": {
|
1223
|
+
"@id": "ex:claim",
|
1224
|
+
"@container": "@graph"
|
1225
|
+
},
|
1226
|
+
"id": "@id"
|
1227
|
+
},
|
1228
|
+
"claim": {
|
1229
|
+
"id": "ex:1",
|
1230
|
+
"test": "foo"
|
1231
|
+
}
|
1232
|
+
})
|
1233
|
+
}
|
839
1234
|
}.each_pair do |title, params|
|
840
1235
|
it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))}
|
841
1236
|
end
|
@@ -888,6 +1283,28 @@ describe JSON::LD::API do
|
|
888
1283
|
}
|
889
1284
|
})
|
890
1285
|
},
|
1286
|
+
"Compacts simple graph with no @index" => {
|
1287
|
+
input: %([{
|
1288
|
+
"http://example.org/input": [{
|
1289
|
+
"@graph": [{
|
1290
|
+
"http://example.org/value": [{"@value": "x"}]
|
1291
|
+
}]
|
1292
|
+
}]
|
1293
|
+
}]),
|
1294
|
+
context: %({
|
1295
|
+
"@vocab": "http://example.org/",
|
1296
|
+
"input": {"@container": ["@graph", "@index", "@set"]}
|
1297
|
+
}),
|
1298
|
+
output: %({
|
1299
|
+
"@context": {
|
1300
|
+
"@vocab": "http://example.org/",
|
1301
|
+
"input": {"@container": ["@graph", "@index", "@set"]}
|
1302
|
+
},
|
1303
|
+
"input": {
|
1304
|
+
"@none": [{"value": "x"}]
|
1305
|
+
}
|
1306
|
+
})
|
1307
|
+
},
|
891
1308
|
"Does not compact graph with @id" => {
|
892
1309
|
input: %([{
|
893
1310
|
"http://example.org/input": [{
|
@@ -910,7 +1327,7 @@ describe JSON::LD::API do
|
|
910
1327
|
"input": {
|
911
1328
|
"@id": "http://example.org/id",
|
912
1329
|
"@index": "g1",
|
913
|
-
"@graph":
|
1330
|
+
"@graph": {"value": "x"}
|
914
1331
|
}
|
915
1332
|
})
|
916
1333
|
},
|
@@ -939,7 +1356,7 @@ describe JSON::LD::API do
|
|
939
1356
|
"input": {"@container": ["@graph", "@id"]}
|
940
1357
|
},
|
941
1358
|
"input": {
|
942
|
-
"
|
1359
|
+
"@none": {"value": "x"}
|
943
1360
|
}
|
944
1361
|
})
|
945
1362
|
},
|
@@ -960,7 +1377,7 @@ describe JSON::LD::API do
|
|
960
1377
|
"@vocab": "http://example.org/",
|
961
1378
|
"input": {"@container": ["@graph", "@id", "@set"]}
|
962
1379
|
},
|
963
|
-
"input": {"
|
1380
|
+
"input": {"@none": [{"value": "x"}]}
|
964
1381
|
})
|
965
1382
|
},
|
966
1383
|
"Compacts simple graph with @index" => {
|
@@ -982,7 +1399,7 @@ describe JSON::LD::API do
|
|
982
1399
|
"input": {"@container": ["@graph", "@id"]}
|
983
1400
|
},
|
984
1401
|
"input": {
|
985
|
-
"
|
1402
|
+
"@none": {"value": "x"}
|
986
1403
|
}
|
987
1404
|
})
|
988
1405
|
},
|
@@ -1032,6 +1449,52 @@ describe JSON::LD::API do
|
|
1032
1449
|
}
|
1033
1450
|
})
|
1034
1451
|
},
|
1452
|
+
"Compacts graph without @id" => {
|
1453
|
+
input: %([{
|
1454
|
+
"http://example.org/input": [{
|
1455
|
+
"@graph": [{
|
1456
|
+
"http://example.org/value": [{"@value": "x"}]
|
1457
|
+
}]
|
1458
|
+
}]
|
1459
|
+
}]),
|
1460
|
+
context: %({
|
1461
|
+
"@vocab": "http://example.org/",
|
1462
|
+
"input": {"@container": ["@graph", "@id"]}
|
1463
|
+
}),
|
1464
|
+
output: %({
|
1465
|
+
"@context": {
|
1466
|
+
"@vocab": "http://example.org/",
|
1467
|
+
"input": {"@container": ["@graph", "@id"]}
|
1468
|
+
},
|
1469
|
+
"input": {
|
1470
|
+
"@none" : {"value": "x"}
|
1471
|
+
}
|
1472
|
+
})
|
1473
|
+
},
|
1474
|
+
"Compacts graph without @id using alias of @none" => {
|
1475
|
+
input: %([{
|
1476
|
+
"http://example.org/input": [{
|
1477
|
+
"@graph": [{
|
1478
|
+
"http://example.org/value": [{"@value": "x"}]
|
1479
|
+
}]
|
1480
|
+
}]
|
1481
|
+
}]),
|
1482
|
+
context: %({
|
1483
|
+
"@vocab": "http://example.org/",
|
1484
|
+
"input": {"@container": ["@graph", "@id"]},
|
1485
|
+
"none": "@none"
|
1486
|
+
}),
|
1487
|
+
output: %({
|
1488
|
+
"@context": {
|
1489
|
+
"@vocab": "http://example.org/",
|
1490
|
+
"input": {"@container": ["@graph", "@id"]},
|
1491
|
+
"none": "@none"
|
1492
|
+
},
|
1493
|
+
"input": {
|
1494
|
+
"none" : {"value": "x"}
|
1495
|
+
}
|
1496
|
+
})
|
1497
|
+
},
|
1035
1498
|
}.each_pair do |title, params|
|
1036
1499
|
it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))}
|
1037
1500
|
end
|
@@ -1040,7 +1503,7 @@ describe JSON::LD::API do
|
|
1040
1503
|
|
1041
1504
|
context "@nest" do
|
1042
1505
|
{
|
1043
|
-
"Indexes to @nest for property with @
|
1506
|
+
"Indexes to @nest for property with @nest" => {
|
1044
1507
|
input: %([{
|
1045
1508
|
"http://example.org/p1": [{"@value": "v1"}],
|
1046
1509
|
"http://example.org/p2": [{"@value": "v2"}]
|
@@ -1060,7 +1523,7 @@ describe JSON::LD::API do
|
|
1060
1523
|
}
|
1061
1524
|
})
|
1062
1525
|
},
|
1063
|
-
"Indexes to @nest for all properties with @
|
1526
|
+
"Indexes to @nest for all properties with @nest" => {
|
1064
1527
|
input: %([{
|
1065
1528
|
"http://example.org/p1": [{"@value": "v1"}],
|
1066
1529
|
"http://example.org/p2": [{"@value": "v2"}]
|
@@ -1566,6 +2029,28 @@ describe JSON::LD::API do
|
|
1566
2029
|
"c": "C in example"
|
1567
2030
|
}),
|
1568
2031
|
},
|
2032
|
+
"orders lexicographically" => {
|
2033
|
+
input: %([{
|
2034
|
+
"@type": ["http://example/t2", "http://example/t1"],
|
2035
|
+
"http://example.org/foo": [
|
2036
|
+
{"@id": "urn:bar"}
|
2037
|
+
]
|
2038
|
+
}]),
|
2039
|
+
context: %({
|
2040
|
+
"@vocab": "http://example/",
|
2041
|
+
"t1": {"@context": {"foo": {"@id": "http://example.com/foo"}}},
|
2042
|
+
"t2": {"@context": {"foo": {"@id": "http://example.org/foo", "@type": "@id"}}}
|
2043
|
+
}),
|
2044
|
+
output: %({
|
2045
|
+
"@context": {
|
2046
|
+
"@vocab": "http://example/",
|
2047
|
+
"t1": {"@context": {"foo": {"@id": "http://example.com/foo"}}},
|
2048
|
+
"t2": {"@context": {"foo": {"@id": "http://example.org/foo", "@type": "@id"}}}
|
2049
|
+
},
|
2050
|
+
"@type": ["t2", "t1"],
|
2051
|
+
"foo": "urn:bar"
|
2052
|
+
}),
|
2053
|
+
},
|
1569
2054
|
"with @container: @type" => {
|
1570
2055
|
input: %([{
|
1571
2056
|
"http://example/typemap": [
|
@@ -1605,41 +2090,53 @@ describe JSON::LD::API do
|
|
1605
2090
|
validate: true,
|
1606
2091
|
exception: JSON::LD::JsonLdError::InvalidTermDefinition
|
1607
2092
|
},
|
1608
|
-
|
1609
|
-
|
1610
|
-
|
1611
|
-
|
1612
|
-
|
1613
|
-
|
1614
|
-
|
1615
|
-
|
1616
|
-
|
1617
|
-
|
2093
|
+
"applies context for all values" => {
|
2094
|
+
input: %([
|
2095
|
+
{
|
2096
|
+
"@id": "http://example.org/id",
|
2097
|
+
"@type": ["http://example/type"],
|
2098
|
+
"http://example/a": [{
|
2099
|
+
"@id": "http://example.org/Foo",
|
2100
|
+
"@type": ["http://example/Foo"],
|
2101
|
+
"http://example/bar": [{"@id": "http://example.org/baz"}]
|
2102
|
+
}]
|
2103
|
+
}
|
2104
|
+
]),
|
2105
|
+
context: %({
|
2106
|
+
"@vocab": "http://example/",
|
2107
|
+
"id": "@id",
|
2108
|
+
"type": "@type",
|
2109
|
+
"Foo": {"@context": {"id": null, "type": null}}
|
1618
2110
|
}),
|
1619
|
-
|
1620
|
-
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
2111
|
+
output: %({
|
2112
|
+
"@context": {
|
2113
|
+
"@vocab": "http://example/",
|
2114
|
+
"id": "@id",
|
2115
|
+
"type": "@type",
|
2116
|
+
"Foo": {"@context": {"id": null, "type": null}}
|
2117
|
+
},
|
2118
|
+
"id": "http://example.org/id",
|
2119
|
+
"type": "http://example/type",
|
2120
|
+
"a": {
|
2121
|
+
"@id": "http://example.org/Foo",
|
2122
|
+
"@type": "Foo",
|
2123
|
+
"bar": {"@id": "http://example.org/baz"}
|
2124
|
+
}
|
1626
2125
|
}),
|
1627
|
-
context: {},
|
1628
|
-
exception: JSON::LD::JsonLdError::ListOfLists
|
1629
2126
|
},
|
1630
|
-
}.
|
1631
|
-
it(title) {run_compact(params)}
|
2127
|
+
}.each_pair do |title, params|
|
2128
|
+
it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))}
|
1632
2129
|
end
|
1633
2130
|
end
|
1634
2131
|
|
1635
2132
|
context "compact IRI selection" do
|
1636
2133
|
{
|
1637
|
-
"
|
2134
|
+
"does not compact using expanded term in 1.0" => {
|
1638
2135
|
input: %({"http://example.org/foo": "term"}),
|
1639
2136
|
context: %({"ex": {"@id": "http://example.org/"}}),
|
1640
2137
|
output: %({
|
1641
2138
|
"@context": {"ex": {"@id": "http://example.org/"}},
|
1642
|
-
"
|
2139
|
+
"http://example.org/foo": "term"
|
1643
2140
|
}),
|
1644
2141
|
processingMode: "json-ld-1.0"
|
1645
2142
|
},
|
@@ -1716,6 +2213,14 @@ describe JSON::LD::API do
|
|
1716
2213
|
"ex:bar": "term"
|
1717
2214
|
})
|
1718
2215
|
},
|
2216
|
+
"compacts using base if @vocab: relative" => {
|
2217
|
+
input: %({"http://example.org/foo/bar": "term"}),
|
2218
|
+
context: %({"@base": "http://example.org/foo/", "@vocab": ""}),
|
2219
|
+
output: %({
|
2220
|
+
"@context": {"@base": "http://example.org/foo/", "@vocab": ""},
|
2221
|
+
"bar": "term"
|
2222
|
+
})
|
2223
|
+
},
|
1719
2224
|
}.each do |title, params|
|
1720
2225
|
it(title) {run_compact(params)}
|
1721
2226
|
end
|