json-ld 3.0.2 → 3.1.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 +4 -4
- data/AUTHORS +1 -1
- data/README.md +90 -53
- data/UNLICENSE +1 -1
- data/VERSION +1 -1
- data/bin/jsonld +4 -4
- data/lib/json/ld.rb +27 -10
- data/lib/json/ld/api.rb +325 -96
- data/lib/json/ld/compact.rb +75 -27
- data/lib/json/ld/conneg.rb +188 -0
- data/lib/json/ld/context.rb +677 -292
- data/lib/json/ld/expand.rb +240 -75
- data/lib/json/ld/flatten.rb +5 -3
- data/lib/json/ld/format.rb +19 -19
- data/lib/json/ld/frame.rb +135 -85
- data/lib/json/ld/from_rdf.rb +44 -17
- data/lib/json/ld/html/nokogiri.rb +151 -0
- data/lib/json/ld/html/rexml.rb +186 -0
- data/lib/json/ld/reader.rb +25 -5
- data/lib/json/ld/resource.rb +2 -2
- data/lib/json/ld/streaming_writer.rb +3 -1
- data/lib/json/ld/to_rdf.rb +47 -17
- data/lib/json/ld/utils.rb +4 -2
- data/lib/json/ld/writer.rb +75 -14
- data/spec/api_spec.rb +13 -34
- data/spec/compact_spec.rb +968 -9
- data/spec/conneg_spec.rb +373 -0
- data/spec/context_spec.rb +447 -53
- data/spec/expand_spec.rb +1872 -416
- data/spec/flatten_spec.rb +434 -47
- data/spec/frame_spec.rb +979 -344
- data/spec/from_rdf_spec.rb +305 -5
- data/spec/spec_helper.rb +177 -0
- data/spec/streaming_writer_spec.rb +4 -4
- data/spec/suite_compact_spec.rb +2 -2
- data/spec/suite_expand_spec.rb +14 -2
- data/spec/suite_flatten_spec.rb +10 -2
- data/spec/suite_frame_spec.rb +3 -2
- data/spec/suite_from_rdf_spec.rb +2 -2
- data/spec/suite_helper.rb +55 -20
- data/spec/suite_html_spec.rb +22 -0
- data/spec/suite_http_spec.rb +35 -0
- data/spec/suite_remote_doc_spec.rb +2 -2
- data/spec/suite_to_rdf_spec.rb +14 -3
- data/spec/support/extensions.rb +5 -1
- data/spec/test-files/test-4-input.json +3 -3
- data/spec/test-files/test-5-input.json +2 -2
- data/spec/test-files/test-8-framed.json +14 -18
- data/spec/to_rdf_spec.rb +606 -16
- data/spec/writer_spec.rb +5 -5
- metadata +144 -88
data/lib/json/ld/resource.rb
CHANGED
@@ -142,8 +142,8 @@ module JSON::LD
|
|
142
142
|
#
|
143
143
|
# @param [Hash] options
|
144
144
|
# @return [String] serizlied JSON representation of resource
|
145
|
-
def to_json(options
|
146
|
-
deresolve.to_json(options)
|
145
|
+
def to_json(**options)
|
146
|
+
deresolve.to_json(**options)
|
147
147
|
end
|
148
148
|
|
149
149
|
##
|
@@ -60,6 +60,8 @@ module JSON::LD
|
|
60
60
|
|
61
61
|
pd << if statement.object.resource?
|
62
62
|
{'@id' => statement.object.to_s}
|
63
|
+
elsif statement.object.datatype == RDF::URI(RDF.to_uri + "JSON")
|
64
|
+
{"@value" => MultiJson.load(statement.object.to_s), "@type" => "@json"}
|
63
65
|
else
|
64
66
|
lit = {"@value" => statement.object.to_s}
|
65
67
|
lit["@type"] = statement.object.datatype.to_s if statement.object.has_datatype?
|
@@ -110,7 +112,7 @@ module JSON::LD
|
|
110
112
|
@output.puts(",") if [:wrote_node, :wrote_graph].include?(@state)
|
111
113
|
if @current_node_def
|
112
114
|
node_def = if context
|
113
|
-
compacted = JSON::LD::API.compact(@current_node_def, context, rename_bnodes: false)
|
115
|
+
compacted = JSON::LD::API.compact(@current_node_def, context, rename_bnodes: false, **@options)
|
114
116
|
compacted.delete('@context')
|
115
117
|
compacted
|
116
118
|
else
|
data/lib/json/ld/to_rdf.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
require 'rdf'
|
4
4
|
require 'rdf/nquads'
|
5
|
+
require 'json/canonicalization'
|
5
6
|
|
6
7
|
module JSON::LD
|
7
8
|
module ToRDF
|
@@ -18,6 +19,8 @@ module JSON::LD
|
|
18
19
|
if value?(item)
|
19
20
|
value, datatype = item.fetch('@value'), item.fetch('@type', nil)
|
20
21
|
|
22
|
+
datatype = RDF::URI(RDF.to_uri + "JSON") if datatype == '@json'
|
23
|
+
|
21
24
|
case value
|
22
25
|
when TrueClass, FalseClass
|
23
26
|
# If value is true or false, then set value its canonical lexical form as defined in the section Data Round Tripping. If datatype is null, set it to xsd:boolean.
|
@@ -25,17 +28,48 @@ module JSON::LD
|
|
25
28
|
datatype ||= RDF::XSD.boolean.to_s
|
26
29
|
when Numeric
|
27
30
|
# Otherwise, if value is a number, then set value to its canonical lexical form as defined in the section Data Round Tripping. If datatype is null, set it to either xsd:integer or xsd:double, depending on if the value contains a fractional and/or an exponential component.
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
+
value = if datatype == RDF::URI(RDF.to_uri + "JSON")
|
32
|
+
value.to_json_c14n
|
33
|
+
else
|
34
|
+
# Don't serialize as double if there are no fractional bits
|
35
|
+
as_double = value.ceil != value || value >= 1e21 || datatype == RDF::XSD.double
|
36
|
+
lit = if as_double
|
37
|
+
RDF::Literal::Double.new(value, canonicalize: true)
|
38
|
+
else
|
39
|
+
RDF::Literal.new(value.numerator, canonicalize: true)
|
40
|
+
end
|
41
|
+
|
42
|
+
datatype ||= lit.datatype
|
43
|
+
lit.to_s.sub("E+", "E")
|
44
|
+
end
|
45
|
+
when Array, Hash
|
46
|
+
# Only valid for rdf:JSON
|
47
|
+
value = value.to_json_c14n
|
31
48
|
else
|
49
|
+
if item.has_key?('@direction') && @options[:rdfDirection]
|
50
|
+
# Either serialize using a datatype, or a compound-literal
|
51
|
+
case @options[:rdfDirection]
|
52
|
+
when 'i18n-datatype'
|
53
|
+
datatype = RDF::URI("https://www.w3.org/ns/i18n##{item.fetch('@language', '')}_#{item['@direction']}")
|
54
|
+
when 'compound-literal'
|
55
|
+
cl = RDF::Node.new
|
56
|
+
yield RDF::Statement(cl, RDF.value, item['@value'].to_s)
|
57
|
+
yield RDF::Statement(cl, RDF.to_uri + 'language', item['@language']) if item['@language']
|
58
|
+
yield RDF::Statement(cl, RDF.to_uri + 'direction', item['@direction'])
|
59
|
+
return cl
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
32
63
|
# Otherwise, if datatype is null, set it to xsd:string or xsd:langString, depending on if item has a @language key.
|
33
64
|
datatype ||= item.has_key?('@language') ? RDF.langString : RDF::XSD.string
|
65
|
+
if datatype == RDF::URI(RDF.to_uri + "JSON")
|
66
|
+
value = value.to_json_c14n
|
67
|
+
end
|
34
68
|
end
|
35
69
|
datatype = RDF::URI(datatype) if datatype && !datatype.is_a?(RDF::URI)
|
36
70
|
|
37
71
|
# 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
|
-
language = item.fetch('@language', nil)
|
72
|
+
language = item.fetch('@language', nil) if datatype == RDF.langString
|
39
73
|
return RDF::Literal.new(value, datatype: datatype, language: language)
|
40
74
|
elsif list?(item)
|
41
75
|
# 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.
|
@@ -65,21 +99,17 @@ module JSON::LD
|
|
65
99
|
#log_debug("item_to_rdf") {"@reverse predicate: #{predicate.to_ntriples rescue 'malformed rdf'}"}
|
66
100
|
# For each item in values
|
67
101
|
vv.each do |v|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
yield RDF::Statement(object, predicate, subject, graph_name: graph_name)
|
74
|
-
else
|
75
|
-
# Otherwise, item is a value object or a node definition. Generate object as the result of the Object Converstion algorithm passing item.
|
76
|
-
object = item_to_rdf(v, graph_name: graph_name, &block)
|
77
|
-
#log_debug("item_to_rdf") {"subject: #{object.to_ntriples rescue 'malformed rdf'}"}
|
78
|
-
# yield subject, prediate, and literal to results.
|
79
|
-
yield RDF::Statement(object, predicate, subject, graph_name: graph_name)
|
80
|
-
end
|
102
|
+
# Item is a node definition. Generate object as the result of the Object Converstion algorithm passing item.
|
103
|
+
object = item_to_rdf(v, graph_name: graph_name, &block)
|
104
|
+
#log_debug("item_to_rdf") {"subject: #{object.to_ntriples rescue 'malformed rdf'}"}
|
105
|
+
# yield subject, prediate, and literal to results.
|
106
|
+
yield RDF::Statement(object, predicate, subject, graph_name: graph_name)
|
81
107
|
end
|
82
108
|
end
|
109
|
+
when '@included'
|
110
|
+
values.each do |v|
|
111
|
+
item_to_rdf(v, graph_name: graph_name, &block)
|
112
|
+
end
|
83
113
|
when /^@/
|
84
114
|
# Otherwise, if @type is any other keyword, skip to the next property-values pair
|
85
115
|
else
|
data/lib/json/ld/utils.rb
CHANGED
@@ -49,7 +49,7 @@ module JSON::LD
|
|
49
49
|
##
|
50
50
|
# Is value an expaned @graph?
|
51
51
|
#
|
52
|
-
# Note: A value is a
|
52
|
+
# Note: A value is a graph if all of these hold true:
|
53
53
|
# 1. It is an object.
|
54
54
|
# 2. It has an `@graph` key.
|
55
55
|
# 3. It may have '@context', '@id' or '@index'
|
@@ -59,8 +59,10 @@ module JSON::LD
|
|
59
59
|
def graph?(value)
|
60
60
|
value.is_a?(Hash) && (value.keys - UTIL_GRAPH_KEYS) == ['@graph']
|
61
61
|
end
|
62
|
+
|
62
63
|
##
|
63
|
-
# Is value a simple
|
64
|
+
# Is value a simple graph (lacking @id)?
|
65
|
+
#
|
64
66
|
# @param [Object] value
|
65
67
|
# @return [Boolean]
|
66
68
|
def simple_graph?(value)
|
data/lib/json/ld/writer.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
# frozen_string_literal: true
|
3
3
|
require 'json/ld/streaming_writer'
|
4
|
+
require 'link_header'
|
5
|
+
|
4
6
|
module JSON::LD
|
5
7
|
##
|
6
8
|
# A JSON-LD parser in Ruby.
|
@@ -50,8 +52,8 @@ module JSON::LD
|
|
50
52
|
#
|
51
53
|
# Select the :expand option to output JSON-LD in expanded form
|
52
54
|
#
|
53
|
-
# @see
|
54
|
-
# @see
|
55
|
+
# @see https://www.w3.org/TR/json-ld11-api/
|
56
|
+
# @see https://www.w3.org/TR/json-ld11-api/#the-normalization-algorithm
|
55
57
|
# @author [Gregg Kellogg](http://greggkellogg.net/)
|
56
58
|
class Writer < RDF::Writer
|
57
59
|
include StreamingWriter
|
@@ -94,17 +96,23 @@ module JSON::LD
|
|
94
96
|
description: "Context to use when compacting.") {|arg| RDF::URI(arg)},
|
95
97
|
RDF::CLI::Option.new(
|
96
98
|
symbol: :embed,
|
97
|
-
datatype: %w(@always @
|
98
|
-
default: '@
|
99
|
+
datatype: %w(@always @once @never),
|
100
|
+
default: '@once',
|
99
101
|
control: :select,
|
100
102
|
on: ["--embed EMBED"],
|
101
|
-
description: "How to embed matched objects (@
|
103
|
+
description: "How to embed matched objects (@once).") {|arg| RDF::URI(arg)},
|
102
104
|
RDF::CLI::Option.new(
|
103
105
|
symbol: :explicit,
|
104
106
|
datatype: TrueClass,
|
105
107
|
control: :checkbox,
|
106
108
|
on: ["--[no-]explicit"],
|
107
109
|
description: "Only include explicitly declared properties in output (false)") {|arg| arg},
|
110
|
+
RDF::CLI::Option.new(
|
111
|
+
symbol: :lowercaseLanguage,
|
112
|
+
datatype: TrueClass,
|
113
|
+
control: :checkbox,
|
114
|
+
on: ["--[no-]lowercase-language"],
|
115
|
+
description: "By default, language tags are left as is. To normalize to lowercase, set this option to `true`."),
|
108
116
|
RDF::CLI::Option.new(
|
109
117
|
symbol: :omitDefault,
|
110
118
|
datatype: TrueClass,
|
@@ -123,6 +131,13 @@ module JSON::LD
|
|
123
131
|
control: :radio,
|
124
132
|
on: ["--processingMode MODE", %w(json-ld-1.0 json-ld-1.1)],
|
125
133
|
description: "Set Processing Mode (json-ld-1.0 or json-ld-1.1)"),
|
134
|
+
RDF::CLI::Option.new(
|
135
|
+
symbol: :rdfDirection,
|
136
|
+
datatype: %w(i18n-datatype compound-literal),
|
137
|
+
default: 'null',
|
138
|
+
control: :select,
|
139
|
+
on: ["--rdf-direction DIR", %w(i18n-datatype compound-literal)],
|
140
|
+
description: "How to serialize literal direction (i18n-datatype compound-literal)") {|arg| RDF::URI(arg)},
|
126
141
|
RDF::CLI::Option.new(
|
127
142
|
symbol: :requireAll,
|
128
143
|
datatype: TrueClass,
|
@@ -136,6 +151,12 @@ module JSON::LD
|
|
136
151
|
control: :checkbox,
|
137
152
|
on: ["--[no-]stream"],
|
138
153
|
description: "Do not attempt to optimize graph presentation, suitable for streaming large graphs.") {|arg| arg},
|
154
|
+
RDF::CLI::Option.new(
|
155
|
+
symbol: :useNativeTypes,
|
156
|
+
datatype: TrueClass,
|
157
|
+
control: :checkbox,
|
158
|
+
on: ["--[no-]use-native-types"],
|
159
|
+
description: "Use native JSON values in value objects.") {|arg| arg},
|
139
160
|
RDF::CLI::Option.new(
|
140
161
|
symbol: :useRdfType,
|
141
162
|
datatype: TrueClass,
|
@@ -145,6 +166,41 @@ module JSON::LD
|
|
145
166
|
]
|
146
167
|
end
|
147
168
|
|
169
|
+
class << self
|
170
|
+
attr_reader :white_list
|
171
|
+
attr_reader :black_list
|
172
|
+
|
173
|
+
##
|
174
|
+
# Use parameters from accept-params to determine if the parameters are acceptable to invoke this writer. The `accept_params` will subsequently be provided to the writer instance.
|
175
|
+
#
|
176
|
+
# @param [Hash{Symbol => String}] accept_params
|
177
|
+
# @yield [accept_params] if a block is given, returns the result of evaluating that block
|
178
|
+
# @yieldparam [Hash{Symbol => String}] accept_params
|
179
|
+
# @return [Boolean]
|
180
|
+
# @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
|
181
|
+
def accept?(accept_params)
|
182
|
+
# Profiles that aren't specific IANA relations represent the URL
|
183
|
+
# of a context or frame that may be subject to black- or white-listing
|
184
|
+
profile = accept_params[:profile].to_s.split(/\s+/)
|
185
|
+
|
186
|
+
if block_given?
|
187
|
+
yield(accept_params)
|
188
|
+
else
|
189
|
+
true
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# Returns default context used for compacted profile without an explicit context URL
|
195
|
+
# @return [String]
|
196
|
+
def default_context; @default_context || JSON::LD::DEFAULT_CONTEXT; end
|
197
|
+
|
198
|
+
##
|
199
|
+
# Sets default context used for compacted profile without an explicit context URL
|
200
|
+
# @param [String] url
|
201
|
+
def default_context=(url); @default_context = url; end
|
202
|
+
end
|
203
|
+
|
148
204
|
##
|
149
205
|
# Initializes the RDF-LD writer instance.
|
150
206
|
#
|
@@ -237,13 +293,19 @@ module JSON::LD
|
|
237
293
|
else
|
238
294
|
|
239
295
|
log_debug("writer") { "serialize #{@repo.count} statements, #{@options.inspect}"}
|
240
|
-
result = API.fromRdf(@repo,
|
296
|
+
result = API.fromRdf(@repo, **@options)
|
297
|
+
|
298
|
+
# Some options may be indicated from accept parameters
|
299
|
+
profile = @options.fetch(:accept_params, {}).fetch(:profile, "").split(' ')
|
300
|
+
links = LinkHeader.parse(@options[:link])
|
301
|
+
@options[:context] ||= links.find_link(['rel', JSON_LD_NS+"context"]).href rescue nil
|
302
|
+
@options[:context] ||= Writer.default_context if profile.include?(JSON_LD_NS+"compacted")
|
303
|
+
@options[:frame] ||= links.find_link(['rel', JSON_LD_NS+"frame"]).href rescue nil
|
241
304
|
|
242
305
|
# If we were provided a context, or prefixes, use them to compact the output
|
243
|
-
context =
|
244
|
-
context ||= @options[:context]
|
306
|
+
context = @options[:context]
|
245
307
|
context ||= if @options[:prefixes] || @options[:language] || @options[:standard_prefixes]
|
246
|
-
ctx = Context.new(
|
308
|
+
ctx = Context.new(**@options)
|
247
309
|
ctx.language = @options[:language] if @options[:language]
|
248
310
|
@options[:prefixes].each do |prefix, iri|
|
249
311
|
ctx.set_mapping(prefix, iri) if prefix && iri
|
@@ -253,18 +315,17 @@ module JSON::LD
|
|
253
315
|
|
254
316
|
# Rename BNodes to uniquify them, if necessary
|
255
317
|
if options[:unique_bnodes]
|
256
|
-
result = API.flatten(result, context,
|
318
|
+
result = API.flatten(result, context, **@options)
|
257
319
|
end
|
258
320
|
|
259
|
-
frame =
|
260
|
-
if frame ||= @options[:frame]
|
321
|
+
if frame = @options[:frame]
|
261
322
|
# Perform framing, if given a frame
|
262
323
|
log_debug("writer") { "frame result"}
|
263
|
-
result = API.frame(result, frame,
|
324
|
+
result = API.frame(result, frame, **@options)
|
264
325
|
elsif context
|
265
326
|
# Perform compaction, if we have a context
|
266
327
|
log_debug("writer") { "compact result"}
|
267
|
-
result = API.compact(result, context,
|
328
|
+
result = API.compact(result, context, **@options)
|
268
329
|
end
|
269
330
|
|
270
331
|
@output.write(result.to_json(JSON_STATE))
|
data/spec/api_spec.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
# coding: utf-8
|
2
3
|
require_relative 'spec_helper'
|
3
4
|
|
@@ -8,54 +9,32 @@ describe JSON::LD::API do
|
|
8
9
|
describe "#initialize" do
|
9
10
|
context "with string input" do
|
10
11
|
let(:context) do
|
11
|
-
JSON::LD::API::RemoteDocument.new(
|
12
|
+
JSON::LD::API::RemoteDocument.new(%q({
|
12
13
|
"@context": {
|
13
14
|
"xsd": "http://www.w3.org/2001/XMLSchema#",
|
14
15
|
"name": "http://xmlns.com/foaf/0.1/name",
|
15
16
|
"homepage": {"@id": "http://xmlns.com/foaf/0.1/homepage", "@type": "@id"},
|
16
17
|
"avatar": {"@id": "http://xmlns.com/foaf/0.1/avatar", "@type": "@id"}
|
17
18
|
}
|
18
|
-
|
19
|
+
}),
|
20
|
+
documentUrl: "http://example.com/context",
|
21
|
+
contentType: 'application/ld+json'
|
22
|
+
)
|
19
23
|
end
|
20
24
|
let(:remote_doc) do
|
21
|
-
JSON::LD::API::RemoteDocument.new("
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
+
JSON::LD::API::RemoteDocument.new(%q({"@id": "", "name": "foo"}),
|
26
|
+
documentUrl: "http://example.com/foo",
|
27
|
+
contentType: 'application/ld+json',
|
28
|
+
contextUrl: "http://example.com/context"
|
29
|
+
)
|
25
30
|
end
|
26
31
|
|
27
32
|
it "loads document with loader and loads context" do
|
28
|
-
expect(described_class).to receive(:documentLoader).with("http://example.com/foo", anything).
|
33
|
+
expect(described_class).to receive(:documentLoader).with("http://example.com/foo", anything).and_yield(remote_doc)
|
29
34
|
expect(described_class).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(context)
|
30
35
|
described_class.new("http://example.com/foo", nil)
|
31
36
|
end
|
32
37
|
end
|
33
|
-
|
34
|
-
context "with RDF::Util::File::RemoteDoc input" do
|
35
|
-
let(:context) do
|
36
|
-
JSON::LD::API::RemoteDocument.new("http://example.com/context", %q({
|
37
|
-
"@context": {
|
38
|
-
"xsd": "http://www.w3.org/2001/XMLSchema#",
|
39
|
-
"name": "http://xmlns.com/foaf/0.1/name",
|
40
|
-
"homepage": {"@id": "http://xmlns.com/foaf/0.1/homepage", "@type": "@id"},
|
41
|
-
"avatar": {"@id": "http://xmlns.com/foaf/0.1/avatar", "@type": "@id"}
|
42
|
-
}
|
43
|
-
}))
|
44
|
-
end
|
45
|
-
let(:remote_doc) do
|
46
|
-
RDF::Util::File::RemoteDocument.new(%q({"@id": "", "name": "foo"}),
|
47
|
-
headers: {
|
48
|
-
content_type: 'application/json',
|
49
|
-
link: %(<http://example.com/context>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json")
|
50
|
-
}
|
51
|
-
)
|
52
|
-
end
|
53
|
-
|
54
|
-
it "processes document and retrieves linked context" do
|
55
|
-
expect(described_class).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(context)
|
56
|
-
described_class.new(remote_doc, nil)
|
57
|
-
end
|
58
|
-
end
|
59
38
|
end
|
60
39
|
|
61
40
|
context "when validating", pending: ("JRuby support for jsonlint" if RUBY_ENGINE == "jruby") do
|
@@ -80,7 +59,7 @@ describe JSON::LD::API do
|
|
80
59
|
it "expands" do
|
81
60
|
options = {logger: logger, adapter: adapter}
|
82
61
|
options[:expandContext] = File.open(context) if context
|
83
|
-
jld = described_class.expand(File.open(filename), options)
|
62
|
+
jld = described_class.expand(File.open(filename), **options)
|
84
63
|
expect(jld).to produce_jsonld(JSON.load(File.open(expanded)), logger)
|
85
64
|
end if File.exist?(expanded)
|
86
65
|
|
data/spec/compact_spec.rb
CHANGED
@@ -125,6 +125,18 @@ describe JSON::LD::API do
|
|
125
125
|
"b": ["c"]
|
126
126
|
})
|
127
127
|
},
|
128
|
+
"@set coercion on @type" => {
|
129
|
+
input: %({
|
130
|
+
"@type": "http://www.w3.org/2000/01/rdf-schema#Resource",
|
131
|
+
"http://example.org/foo": {"@value": "bar", "@type": "http://example.com/type"}
|
132
|
+
}),
|
133
|
+
context: %({"@version": 1.1, "@type": {"@container": "@set"}}),
|
134
|
+
output: %({
|
135
|
+
"@context": {"@version": 1.1, "@type": {"@container": "@set"}},
|
136
|
+
"@type": ["http://www.w3.org/2000/01/rdf-schema#Resource"],
|
137
|
+
"http://example.org/foo": {"@value": "bar", "@type": "http://example.com/type"}
|
138
|
+
})
|
139
|
+
},
|
128
140
|
"empty @set coercion" => {
|
129
141
|
input: %({
|
130
142
|
"http://example.com/b": []
|
@@ -176,6 +188,25 @@ describe JSON::LD::API do
|
|
176
188
|
"term5": [ "v5", "plain literal" ]
|
177
189
|
})
|
178
190
|
},
|
191
|
+
"default direction" => {
|
192
|
+
input: %({
|
193
|
+
"http://example.com/term": [
|
194
|
+
"v5",
|
195
|
+
{"@value": "plain literal"}
|
196
|
+
]
|
197
|
+
}),
|
198
|
+
context: %({
|
199
|
+
"term5": {"@id": "http://example.com/term", "@direction": null},
|
200
|
+
"@direction": "ltr"
|
201
|
+
}),
|
202
|
+
output: %({
|
203
|
+
"@context": {
|
204
|
+
"term5": {"@id": "http://example.com/term", "@direction": null},
|
205
|
+
"@direction": "ltr"
|
206
|
+
},
|
207
|
+
"term5": [ "v5", "plain literal" ]
|
208
|
+
})
|
209
|
+
},
|
179
210
|
}.each_pair do |title, params|
|
180
211
|
it(title) {run_compact(params)}
|
181
212
|
end
|
@@ -206,6 +237,19 @@ describe JSON::LD::API do
|
|
206
237
|
"http://example.org/foo": {"@value": "bar", "type": "http://example.com/type"}
|
207
238
|
})
|
208
239
|
},
|
240
|
+
"@type with @container: @set": {
|
241
|
+
input: %({
|
242
|
+
"@type": "http://www.w3.org/2000/01/rdf-schema#Resource",
|
243
|
+
"http://example.org/foo": {"@value": "bar", "@type": "http://example.com/type"}
|
244
|
+
}),
|
245
|
+
context: %({"type": {"@id": "@type", "@container": "@set"}}),
|
246
|
+
output: %({
|
247
|
+
"@context": {"type": {"@id": "@type", "@container": "@set"}},
|
248
|
+
"type": ["http://www.w3.org/2000/01/rdf-schema#Resource"],
|
249
|
+
"http://example.org/foo": {"@value": "bar", "type": "http://example.com/type"}
|
250
|
+
}),
|
251
|
+
processingMode: 'json-ld-1.1'
|
252
|
+
},
|
209
253
|
"@language" => {
|
210
254
|
input: %({
|
211
255
|
"http://example.org/foo": {"@value": "bar", "@language": "baz"}
|
@@ -216,6 +260,16 @@ describe JSON::LD::API do
|
|
216
260
|
"http://example.org/foo": {"@value": "bar", "language": "baz"}
|
217
261
|
})
|
218
262
|
},
|
263
|
+
"@direction" => {
|
264
|
+
input: %({
|
265
|
+
"http://example.org/foo": {"@value": "bar", "@direction": "ltr"}
|
266
|
+
}),
|
267
|
+
context: %({"direction": "@direction"}),
|
268
|
+
output: %({
|
269
|
+
"@context": {"direction": "@direction"},
|
270
|
+
"http://example.org/foo": {"@value": "bar", "direction": "ltr"}
|
271
|
+
})
|
272
|
+
},
|
219
273
|
"@value" => {
|
220
274
|
input: %({
|
221
275
|
"http://example.org/foo": {"@value": "bar", "@language": "baz"}
|
@@ -259,6 +313,22 @@ describe JSON::LD::API do
|
|
259
313
|
"term5": "v1"
|
260
314
|
})
|
261
315
|
},
|
316
|
+
"Uses term with null direction when two terms conflict on direction" => {
|
317
|
+
input: %([{
|
318
|
+
"http://example.com/term": {"@value": "v1"}
|
319
|
+
}]),
|
320
|
+
context: %({
|
321
|
+
"term5": {"@id": "http://example.com/term","@direction": null},
|
322
|
+
"@direction": "ltr"
|
323
|
+
}),
|
324
|
+
output: %({
|
325
|
+
"@context": {
|
326
|
+
"term5": {"@id": "http://example.com/term","@direction": null},
|
327
|
+
"@direction": "ltr"
|
328
|
+
},
|
329
|
+
"term5": "v1"
|
330
|
+
})
|
331
|
+
},
|
262
332
|
"Uses subject alias" => {
|
263
333
|
input: %([{
|
264
334
|
"@id": "http://example.com/id1",
|
@@ -489,7 +559,9 @@ describe JSON::LD::API do
|
|
489
559
|
|
490
560
|
context "context as reference" do
|
491
561
|
let(:remote_doc) do
|
492
|
-
JSON::LD::API::RemoteDocument.new(
|
562
|
+
JSON::LD::API::RemoteDocument.new(
|
563
|
+
%q({"@context": {"b": "http://example.com/b"}}),
|
564
|
+
documentUrl: "http://example.com/context")
|
493
565
|
end
|
494
566
|
it "uses referenced context" do
|
495
567
|
input = ::JSON.parse %({
|
@@ -527,6 +599,26 @@ describe JSON::LD::API do
|
|
527
599
|
"foo_de": ["de"]
|
528
600
|
})
|
529
601
|
},
|
602
|
+
"1 term 2 lists 2 directions" => {
|
603
|
+
input: %([{
|
604
|
+
"http://example.com/foo": [
|
605
|
+
{"@list": [{"@value": "en", "@direction": "ltr"}]},
|
606
|
+
{"@list": [{"@value": "ar", "@direction": "rtl"}]}
|
607
|
+
]
|
608
|
+
}]),
|
609
|
+
context: %({
|
610
|
+
"foo_ltr": {"@id": "http://example.com/foo", "@container": "@list", "@direction": "ltr"},
|
611
|
+
"foo_rtl": {"@id": "http://example.com/foo", "@container": "@list", "@direction": "rtl"}
|
612
|
+
}),
|
613
|
+
output: %({
|
614
|
+
"@context": {
|
615
|
+
"foo_ltr": {"@id": "http://example.com/foo", "@container": "@list", "@direction": "ltr"},
|
616
|
+
"foo_rtl": {"@id": "http://example.com/foo", "@container": "@list", "@direction": "rtl"}
|
617
|
+
},
|
618
|
+
"foo_ltr": ["en"],
|
619
|
+
"foo_rtl": ["ar"]
|
620
|
+
})
|
621
|
+
},
|
530
622
|
"coerced @list containing an empty list" => {
|
531
623
|
input: %([{
|
532
624
|
"http://example.com/foo": [{"@list": [{"@list": []}]}]
|
@@ -598,6 +690,145 @@ describe JSON::LD::API do
|
|
598
690
|
end
|
599
691
|
end
|
600
692
|
|
693
|
+
context "with @type: @json" do
|
694
|
+
{
|
695
|
+
"true": {
|
696
|
+
output: %({
|
697
|
+
"@context": {
|
698
|
+
"@version": 1.1,
|
699
|
+
"e": {"@id": "http://example.org/vocab#bool", "@type": "@json"}
|
700
|
+
},
|
701
|
+
"e": true
|
702
|
+
}),
|
703
|
+
input:%( [{
|
704
|
+
"http://example.org/vocab#bool": [{"@value": true, "@type": "@json"}]
|
705
|
+
}]),
|
706
|
+
},
|
707
|
+
"false": {
|
708
|
+
output: %({
|
709
|
+
"@context": {
|
710
|
+
"@version": 1.1,
|
711
|
+
"e": {"@id": "http://example.org/vocab#bool", "@type": "@json"}
|
712
|
+
},
|
713
|
+
"e": false
|
714
|
+
}),
|
715
|
+
input: %([{
|
716
|
+
"http://example.org/vocab#bool": [{"@value": false, "@type": "@json"}]
|
717
|
+
}]),
|
718
|
+
},
|
719
|
+
"double": {
|
720
|
+
output: %({
|
721
|
+
"@context": {
|
722
|
+
"@version": 1.1,
|
723
|
+
"e": {"@id": "http://example.org/vocab#double", "@type": "@json"}
|
724
|
+
},
|
725
|
+
"e": 1.23
|
726
|
+
}),
|
727
|
+
input: %([{
|
728
|
+
"http://example.org/vocab#double": [{"@value": 1.23, "@type": "@json"}]
|
729
|
+
}]),
|
730
|
+
},
|
731
|
+
"double-zero": {
|
732
|
+
output: %({
|
733
|
+
"@context": {
|
734
|
+
"@version": 1.1,
|
735
|
+
"e": {"@id": "http://example.org/vocab#double", "@type": "@json"}
|
736
|
+
},
|
737
|
+
"e": 0.0e0
|
738
|
+
}),
|
739
|
+
input: %([{
|
740
|
+
"http://example.org/vocab#double": [{"@value": 0.0e0, "@type": "@json"}]
|
741
|
+
}]),
|
742
|
+
},
|
743
|
+
"integer": {
|
744
|
+
output: %({
|
745
|
+
"@context": {
|
746
|
+
"@version": 1.1,
|
747
|
+
"e": {"@id": "http://example.org/vocab#integer", "@type": "@json"}
|
748
|
+
},
|
749
|
+
"e": 123
|
750
|
+
}),
|
751
|
+
input: %([{
|
752
|
+
"http://example.org/vocab#integer": [{"@value": 123, "@type": "@json"}]
|
753
|
+
}]),
|
754
|
+
},
|
755
|
+
"string": {
|
756
|
+
input: %([{
|
757
|
+
"http://example.org/vocab#string": [{
|
758
|
+
"@value": "string",
|
759
|
+
"@type": "@json"
|
760
|
+
}]
|
761
|
+
}]),
|
762
|
+
output: %({
|
763
|
+
"@context": {
|
764
|
+
"@version": 1.1,
|
765
|
+
"e": {"@id": "http://example.org/vocab#string", "@type": "@json"}
|
766
|
+
},
|
767
|
+
"e": "string"
|
768
|
+
})
|
769
|
+
},
|
770
|
+
"null": {
|
771
|
+
input: %([{
|
772
|
+
"http://example.org/vocab#null": [{
|
773
|
+
"@value": null,
|
774
|
+
"@type": "@json"
|
775
|
+
}]
|
776
|
+
}]),
|
777
|
+
output: %({
|
778
|
+
"@context": {
|
779
|
+
"@version": 1.1,
|
780
|
+
"e": {"@id": "http://example.org/vocab#null", "@type": "@json"}
|
781
|
+
},
|
782
|
+
"e": null
|
783
|
+
})
|
784
|
+
},
|
785
|
+
"object": {
|
786
|
+
output: %({
|
787
|
+
"@context": {
|
788
|
+
"@version": 1.1,
|
789
|
+
"e": {"@id": "http://example.org/vocab#object", "@type": "@json"}
|
790
|
+
},
|
791
|
+
"e": {"foo": "bar"}
|
792
|
+
}),
|
793
|
+
input: %([{
|
794
|
+
"http://example.org/vocab#object": [{"@value": {"foo": "bar"}, "@type": "@json"}]
|
795
|
+
}]),
|
796
|
+
},
|
797
|
+
"array": {
|
798
|
+
output: %({
|
799
|
+
"@context": {
|
800
|
+
"@version": 1.1,
|
801
|
+
"e": {"@id": "http://example.org/vocab#array", "@type": "@json", "@container": "@set"}
|
802
|
+
},
|
803
|
+
"e": [{"foo": "bar"}]
|
804
|
+
}),
|
805
|
+
input: %([{
|
806
|
+
"http://example.org/vocab#array": [{"@value": [{"foo": "bar"}], "@type": "@json"}]
|
807
|
+
}]),
|
808
|
+
},
|
809
|
+
"Already expanded object": {
|
810
|
+
output: %({
|
811
|
+
"@context": {"@version": 1.1},
|
812
|
+
"http://example.org/vocab#object": {"@value": {"foo": "bar"}, "@type": "@json"}
|
813
|
+
}),
|
814
|
+
input: %([{
|
815
|
+
"http://example.org/vocab#object": [{"@value": {"foo": "bar"}, "@type": "@json"}]
|
816
|
+
}]),
|
817
|
+
},
|
818
|
+
"Already expanded object with aliased keys": {
|
819
|
+
output: %({
|
820
|
+
"@context": {"@version": 1.1, "value": "@value", "type": "@type", "json": "@json"},
|
821
|
+
"http://example.org/vocab#object": {"value": {"foo": "bar"}, "type": "json"}
|
822
|
+
}),
|
823
|
+
input: %([{
|
824
|
+
"http://example.org/vocab#object": [{"@value": {"foo": "bar"}, "@type": "@json"}]
|
825
|
+
}])
|
826
|
+
},
|
827
|
+
}.each do |title, params|
|
828
|
+
it(title) {run_compact(processingMode: 'json-ld-1.1', **params)}
|
829
|
+
end
|
830
|
+
end
|
831
|
+
|
601
832
|
context "@container: @index" do
|
602
833
|
{
|
603
834
|
"compact-0029" => {
|
@@ -725,6 +956,164 @@ describe JSON::LD::API do
|
|
725
956
|
}.each_pair do |title, params|
|
726
957
|
it(title) {run_compact(params)}
|
727
958
|
end
|
959
|
+
|
960
|
+
context "@index: property" do
|
961
|
+
{
|
962
|
+
"property-valued index indexes property value, instead of property (value)": {
|
963
|
+
output: %({
|
964
|
+
"@context": {
|
965
|
+
"@version": 1.1,
|
966
|
+
"@base": "http://example.com/",
|
967
|
+
"@vocab": "http://example.com/",
|
968
|
+
"author": {"@type": "@id", "@container": "@index", "@index": "prop"}
|
969
|
+
},
|
970
|
+
"@id": "article",
|
971
|
+
"author": {
|
972
|
+
"regular": {"@id": "person/1"},
|
973
|
+
"guest": [{"@id": "person/2"}, {"@id": "person/3"}]
|
974
|
+
}
|
975
|
+
}),
|
976
|
+
input: %([{
|
977
|
+
"@id": "http://example.com/article",
|
978
|
+
"http://example.com/author": [
|
979
|
+
{"@id": "http://example.com/person/1", "http://example.com/prop": [{"@value": "regular"}]},
|
980
|
+
{"@id": "http://example.com/person/2", "http://example.com/prop": [{"@value": "guest"}]},
|
981
|
+
{"@id": "http://example.com/person/3", "http://example.com/prop": [{"@value": "guest"}]}
|
982
|
+
]
|
983
|
+
}])
|
984
|
+
},
|
985
|
+
"property-valued index indexes property value, instead of @index (multiple values)": {
|
986
|
+
output: %({
|
987
|
+
"@context": {
|
988
|
+
"@version": 1.1,
|
989
|
+
"@base": "http://example.com/",
|
990
|
+
"@vocab": "http://example.com/",
|
991
|
+
"author": {"@type": "@id", "@container": "@index", "@index": "prop"}
|
992
|
+
},
|
993
|
+
"@id": "article",
|
994
|
+
"author": {
|
995
|
+
"regular": {"@id": "person/1", "prop": "foo"},
|
996
|
+
"guest": [
|
997
|
+
{"@id": "person/2", "prop": "foo"},
|
998
|
+
{"@id": "person/3", "prop": "foo"}
|
999
|
+
]
|
1000
|
+
}
|
1001
|
+
}),
|
1002
|
+
input: %([{
|
1003
|
+
"@id": "http://example.com/article",
|
1004
|
+
"http://example.com/author": [
|
1005
|
+
{"@id": "http://example.com/person/1", "http://example.com/prop": [{"@value": "regular"}, {"@value": "foo"}]},
|
1006
|
+
{"@id": "http://example.com/person/2", "http://example.com/prop": [{"@value": "guest"}, {"@value": "foo"}]},
|
1007
|
+
{"@id": "http://example.com/person/3", "http://example.com/prop": [{"@value": "guest"}, {"@value": "foo"}]}
|
1008
|
+
]
|
1009
|
+
}])
|
1010
|
+
},
|
1011
|
+
"property-valued index extracts property value, instead of @index (node)": {
|
1012
|
+
output: %({
|
1013
|
+
"@context": {
|
1014
|
+
"@version": 1.1,
|
1015
|
+
"@base": "http://example.com/",
|
1016
|
+
"@vocab": "http://example.com/",
|
1017
|
+
"author": {"@type": "@vocab", "@container": "@index", "@index": "prop"},
|
1018
|
+
"prop": {"@type": "@id"}
|
1019
|
+
},
|
1020
|
+
"@id": "article",
|
1021
|
+
"author": {
|
1022
|
+
"regular": {"@id": "person/1"},
|
1023
|
+
"guest": [
|
1024
|
+
{"@id": "person/2"},
|
1025
|
+
{"@id": "person/3"}
|
1026
|
+
]
|
1027
|
+
}
|
1028
|
+
}),
|
1029
|
+
input: %([{
|
1030
|
+
"@id": "http://example.com/article",
|
1031
|
+
"http://example.com/author": [
|
1032
|
+
{"@id": "http://example.com/person/1", "http://example.com/prop": [{"@id": "http://example.com/regular"}]},
|
1033
|
+
{"@id": "http://example.com/person/2", "http://example.com/prop": [{"@id": "http://example.com/guest"}]},
|
1034
|
+
{"@id": "http://example.com/person/3", "http://example.com/prop": [{"@id": "http://example.com/guest"}]}
|
1035
|
+
]
|
1036
|
+
}])
|
1037
|
+
},
|
1038
|
+
"property-valued index indexes property value, instead of property (multimple nodes)": {
|
1039
|
+
output: %({
|
1040
|
+
"@context": {
|
1041
|
+
"@version": 1.1,
|
1042
|
+
"@base": "http://example.com/",
|
1043
|
+
"@vocab": "http://example.com/",
|
1044
|
+
"author": {"@type": "@vocab", "@container": "@index", "@index": "prop"},
|
1045
|
+
"prop": {"@type": "@id"}
|
1046
|
+
},
|
1047
|
+
"@id": "article",
|
1048
|
+
"author": {
|
1049
|
+
"regular": {"@id": "person/1", "prop": "foo"},
|
1050
|
+
"guest": [
|
1051
|
+
{"@id": "person/2", "prop": "foo"},
|
1052
|
+
{"@id": "person/3", "prop": "foo"}
|
1053
|
+
]
|
1054
|
+
}
|
1055
|
+
}),
|
1056
|
+
input: %([{
|
1057
|
+
"@id": "http://example.com/article",
|
1058
|
+
"http://example.com/author": [
|
1059
|
+
{"@id": "http://example.com/person/1", "http://example.com/prop": [{"@id": "http://example.com/regular"}, {"@id": "http://example.com/foo"}]},
|
1060
|
+
{"@id": "http://example.com/person/2", "http://example.com/prop": [{"@id": "http://example.com/guest"}, {"@id": "http://example.com/foo"}]},
|
1061
|
+
{"@id": "http://example.com/person/3", "http://example.com/prop": [{"@id": "http://example.com/guest"}, {"@id": "http://example.com/foo"}]}
|
1062
|
+
]
|
1063
|
+
}])
|
1064
|
+
},
|
1065
|
+
"property-valued index indexes using @none if no property value exists": {
|
1066
|
+
output: %({
|
1067
|
+
"@context": {
|
1068
|
+
"@version": 1.1,
|
1069
|
+
"@base": "http://example.com/",
|
1070
|
+
"@vocab": "http://example.com/",
|
1071
|
+
"author": {"@type": "@id", "@container": "@index", "@index": "prop"}
|
1072
|
+
},
|
1073
|
+
"@id": "article",
|
1074
|
+
"author": {
|
1075
|
+
"@none": ["person/1", "person/2", "person/3"]
|
1076
|
+
}
|
1077
|
+
}),
|
1078
|
+
input: %([{
|
1079
|
+
"@id": "http://example.com/article",
|
1080
|
+
"http://example.com/author": [
|
1081
|
+
{"@id": "http://example.com/person/1"},
|
1082
|
+
{"@id": "http://example.com/person/2"},
|
1083
|
+
{"@id": "http://example.com/person/3"}
|
1084
|
+
]
|
1085
|
+
}])
|
1086
|
+
},
|
1087
|
+
"property-valued index indexes using @none if no property value does not compact to string": {
|
1088
|
+
output: %({
|
1089
|
+
"@context": {
|
1090
|
+
"@version": 1.1,
|
1091
|
+
"@base": "http://example.com/",
|
1092
|
+
"@vocab": "http://example.com/",
|
1093
|
+
"author": {"@type": "@id", "@container": "@index", "@index": "prop"}
|
1094
|
+
},
|
1095
|
+
"@id": "article",
|
1096
|
+
"author": {
|
1097
|
+
"@none": [
|
1098
|
+
{"@id": "person/1", "prop": {"@id": "regular"}},
|
1099
|
+
{"@id": "person/2", "prop": {"@id": "guest"}},
|
1100
|
+
{"@id": "person/3", "prop": {"@id": "guest"}}
|
1101
|
+
]
|
1102
|
+
}
|
1103
|
+
}),
|
1104
|
+
input: %([{
|
1105
|
+
"@id": "http://example.com/article",
|
1106
|
+
"http://example.com/author": [
|
1107
|
+
{"@id": "http://example.com/person/1", "http://example.com/prop": [{"@id": "http://example.com/regular"}]},
|
1108
|
+
{"@id": "http://example.com/person/2", "http://example.com/prop": [{"@id": "http://example.com/guest"}]},
|
1109
|
+
{"@id": "http://example.com/person/3", "http://example.com/prop": [{"@id": "http://example.com/guest"}]}
|
1110
|
+
]
|
1111
|
+
}])
|
1112
|
+
}
|
1113
|
+
}.each do |title, params|
|
1114
|
+
it(title) {run_compact(**params)}
|
1115
|
+
end
|
1116
|
+
end
|
728
1117
|
end
|
729
1118
|
|
730
1119
|
context "@container: @language" do
|
@@ -816,6 +1205,173 @@ describe JSON::LD::API do
|
|
816
1205
|
}),
|
817
1206
|
processingMode: "json-ld-1.1"
|
818
1207
|
},
|
1208
|
+
"simple map with term direction": {
|
1209
|
+
input: %([
|
1210
|
+
{
|
1211
|
+
"@id": "http://example.com/queen",
|
1212
|
+
"http://example.com/vocab/label": [
|
1213
|
+
{"@value": "Die Königin", "@language": "de", "@direction": "ltr"},
|
1214
|
+
{"@value": "Ihre Majestät", "@language": "de", "@direction": "ltr"},
|
1215
|
+
{"@value": "The Queen", "@language": "en", "@direction": "ltr"}
|
1216
|
+
]
|
1217
|
+
}
|
1218
|
+
]),
|
1219
|
+
context: %({
|
1220
|
+
"@context": {
|
1221
|
+
"@version": 1.1,
|
1222
|
+
"vocab": "http://example.com/vocab/",
|
1223
|
+
"label": {
|
1224
|
+
"@id": "vocab:label",
|
1225
|
+
"@direction": "ltr",
|
1226
|
+
"@container": "@language"
|
1227
|
+
}
|
1228
|
+
}
|
1229
|
+
}),
|
1230
|
+
output: %({
|
1231
|
+
"@context": {
|
1232
|
+
"@version": 1.1,
|
1233
|
+
"vocab": "http://example.com/vocab/",
|
1234
|
+
"label": {
|
1235
|
+
"@id": "vocab:label",
|
1236
|
+
"@direction": "ltr",
|
1237
|
+
"@container": "@language"
|
1238
|
+
}
|
1239
|
+
},
|
1240
|
+
"@id": "http://example.com/queen",
|
1241
|
+
"label": {
|
1242
|
+
"en": "The Queen",
|
1243
|
+
"de": [ "Die Königin", "Ihre Majestät" ]
|
1244
|
+
}
|
1245
|
+
}),
|
1246
|
+
processingMode: "json-ld-1.1"
|
1247
|
+
},
|
1248
|
+
"simple map with overriding term direction": {
|
1249
|
+
input: %([
|
1250
|
+
{
|
1251
|
+
"@id": "http://example.com/queen",
|
1252
|
+
"http://example.com/vocab/label": [
|
1253
|
+
{"@value": "Die Königin", "@language": "de", "@direction": "ltr"},
|
1254
|
+
{"@value": "Ihre Majestät", "@language": "de", "@direction": "ltr"},
|
1255
|
+
{"@value": "The Queen", "@language": "en", "@direction": "ltr"}
|
1256
|
+
]
|
1257
|
+
}
|
1258
|
+
]),
|
1259
|
+
context: %({
|
1260
|
+
"@context": {
|
1261
|
+
"@version": 1.1,
|
1262
|
+
"@direction": "rtl",
|
1263
|
+
"vocab": "http://example.com/vocab/",
|
1264
|
+
"label": {
|
1265
|
+
"@id": "vocab:label",
|
1266
|
+
"@direction": "ltr",
|
1267
|
+
"@container": "@language"
|
1268
|
+
}
|
1269
|
+
}
|
1270
|
+
}),
|
1271
|
+
output: %({
|
1272
|
+
"@context": {
|
1273
|
+
"@version": 1.1,
|
1274
|
+
"@direction": "rtl",
|
1275
|
+
"vocab": "http://example.com/vocab/",
|
1276
|
+
"label": {
|
1277
|
+
"@id": "vocab:label",
|
1278
|
+
"@direction": "ltr",
|
1279
|
+
"@container": "@language"
|
1280
|
+
}
|
1281
|
+
},
|
1282
|
+
"@id": "http://example.com/queen",
|
1283
|
+
"label": {
|
1284
|
+
"en": "The Queen",
|
1285
|
+
"de": [ "Die Königin", "Ihre Majestät" ]
|
1286
|
+
}
|
1287
|
+
}),
|
1288
|
+
processingMode: "json-ld-1.1"
|
1289
|
+
},
|
1290
|
+
"simple map with overriding null direction": {
|
1291
|
+
input: %([
|
1292
|
+
{
|
1293
|
+
"@id": "http://example.com/queen",
|
1294
|
+
"http://example.com/vocab/label": [
|
1295
|
+
{"@value": "Die Königin", "@language": "de"},
|
1296
|
+
{"@value": "Ihre Majestät", "@language": "de"},
|
1297
|
+
{"@value": "The Queen", "@language": "en"}
|
1298
|
+
]
|
1299
|
+
}
|
1300
|
+
]),
|
1301
|
+
context: %({
|
1302
|
+
"@context": {
|
1303
|
+
"@version": 1.1,
|
1304
|
+
"@direction": "rtl",
|
1305
|
+
"vocab": "http://example.com/vocab/",
|
1306
|
+
"label": {
|
1307
|
+
"@id": "vocab:label",
|
1308
|
+
"@direction": null,
|
1309
|
+
"@container": "@language"
|
1310
|
+
}
|
1311
|
+
}
|
1312
|
+
}),
|
1313
|
+
output: %({
|
1314
|
+
"@context": {
|
1315
|
+
"@version": 1.1,
|
1316
|
+
"@direction": "rtl",
|
1317
|
+
"vocab": "http://example.com/vocab/",
|
1318
|
+
"label": {
|
1319
|
+
"@id": "vocab:label",
|
1320
|
+
"@direction": null,
|
1321
|
+
"@container": "@language"
|
1322
|
+
}
|
1323
|
+
},
|
1324
|
+
"@id": "http://example.com/queen",
|
1325
|
+
"label": {
|
1326
|
+
"en": "The Queen",
|
1327
|
+
"de": [ "Die Königin", "Ihre Majestät" ]
|
1328
|
+
}
|
1329
|
+
}),
|
1330
|
+
processingMode: "json-ld-1.1"
|
1331
|
+
},
|
1332
|
+
"simple map with mismatching term direction": {
|
1333
|
+
input: %([
|
1334
|
+
{
|
1335
|
+
"@id": "http://example.com/queen",
|
1336
|
+
"http://example.com/vocab/label": [
|
1337
|
+
{"@value": "Die Königin", "@language": "de"},
|
1338
|
+
{"@value": "Ihre Majestät", "@language": "de", "@direction": "ltr"},
|
1339
|
+
{"@value": "The Queen", "@language": "en", "@direction": "rtl"}
|
1340
|
+
]
|
1341
|
+
}
|
1342
|
+
]),
|
1343
|
+
context: %({
|
1344
|
+
"@context": {
|
1345
|
+
"@version": 1.1,
|
1346
|
+
"vocab": "http://example.com/vocab/",
|
1347
|
+
"label": {
|
1348
|
+
"@id": "vocab:label",
|
1349
|
+
"@direction": "rtl",
|
1350
|
+
"@container": "@language"
|
1351
|
+
}
|
1352
|
+
}
|
1353
|
+
}),
|
1354
|
+
output: %({
|
1355
|
+
"@context": {
|
1356
|
+
"@version": 1.1,
|
1357
|
+
"vocab": "http://example.com/vocab/",
|
1358
|
+
"label": {
|
1359
|
+
"@id": "vocab:label",
|
1360
|
+
"@direction": "rtl",
|
1361
|
+
"@container": "@language"
|
1362
|
+
}
|
1363
|
+
},
|
1364
|
+
"@id": "http://example.com/queen",
|
1365
|
+
"label": {
|
1366
|
+
"en": "The Queen"
|
1367
|
+
},
|
1368
|
+
"vocab:label": [
|
1369
|
+
{"@value": "Die Königin", "@language": "de"},
|
1370
|
+
{"@value": "Ihre Majestät", "@language": "de", "@direction": "ltr"}
|
1371
|
+
]
|
1372
|
+
}),
|
1373
|
+
processingMode: "json-ld-1.1"
|
1374
|
+
},
|
819
1375
|
}.each_pair do |title, params|
|
820
1376
|
it(title) {run_compact(params)}
|
821
1377
|
end
|
@@ -1160,6 +1716,35 @@ describe JSON::LD::API do
|
|
1160
1716
|
}
|
1161
1717
|
})
|
1162
1718
|
},
|
1719
|
+
"Compacts simple graph with @index and multiple nodes" => {
|
1720
|
+
input: %([{
|
1721
|
+
"http://example.org/input": [{
|
1722
|
+
"@graph": [{
|
1723
|
+
"http://example.org/value": [{"@value": "x"}]
|
1724
|
+
}, {
|
1725
|
+
"http://example.org/value": [{"@value": "y"}]
|
1726
|
+
}],
|
1727
|
+
"@index": "ndx"
|
1728
|
+
}]
|
1729
|
+
}]),
|
1730
|
+
context: %({
|
1731
|
+
"@vocab": "http://example.org/",
|
1732
|
+
"input": {"@container": "@graph"}
|
1733
|
+
}),
|
1734
|
+
output: %({
|
1735
|
+
"@context": {
|
1736
|
+
"@vocab": "http://example.org/",
|
1737
|
+
"input": {"@container": "@graph"}
|
1738
|
+
},
|
1739
|
+
"input": {
|
1740
|
+
"@included": [{
|
1741
|
+
"value": "x"
|
1742
|
+
}, {
|
1743
|
+
"value": "y"
|
1744
|
+
}]
|
1745
|
+
}
|
1746
|
+
})
|
1747
|
+
},
|
1163
1748
|
"Does not compact graph with @id" => {
|
1164
1749
|
input: %([{
|
1165
1750
|
"http://example.org/input": [{
|
@@ -1501,6 +2086,116 @@ describe JSON::LD::API do
|
|
1501
2086
|
end
|
1502
2087
|
end
|
1503
2088
|
|
2089
|
+
context "@included" do
|
2090
|
+
{
|
2091
|
+
"Basic Included array": {
|
2092
|
+
output: %({
|
2093
|
+
"@context": {
|
2094
|
+
"@version": 1.1,
|
2095
|
+
"@vocab": "http://example.org/",
|
2096
|
+
"included": {"@id": "@included", "@container": "@set"}
|
2097
|
+
},
|
2098
|
+
"prop": "value",
|
2099
|
+
"included": [{
|
2100
|
+
"prop": "value2"
|
2101
|
+
}]
|
2102
|
+
}),
|
2103
|
+
input: %([{
|
2104
|
+
"http://example.org/prop": [{"@value": "value"}],
|
2105
|
+
"@included": [{
|
2106
|
+
"http://example.org/prop": [{"@value": "value2"}]
|
2107
|
+
}]
|
2108
|
+
}])
|
2109
|
+
},
|
2110
|
+
"Basic Included object": {
|
2111
|
+
output: %({
|
2112
|
+
"@context": {
|
2113
|
+
"@version": 1.1,
|
2114
|
+
"@vocab": "http://example.org/"
|
2115
|
+
},
|
2116
|
+
"prop": "value",
|
2117
|
+
"@included": {
|
2118
|
+
"prop": "value2"
|
2119
|
+
}
|
2120
|
+
}),
|
2121
|
+
input: %([{
|
2122
|
+
"http://example.org/prop": [{"@value": "value"}],
|
2123
|
+
"@included": [{
|
2124
|
+
"http://example.org/prop": [{"@value": "value2"}]
|
2125
|
+
}]
|
2126
|
+
}])
|
2127
|
+
},
|
2128
|
+
"Multiple properties mapping to @included are folded together": {
|
2129
|
+
output: %({
|
2130
|
+
"@context": {
|
2131
|
+
"@version": 1.1,
|
2132
|
+
"@vocab": "http://example.org/",
|
2133
|
+
"included1": "@included",
|
2134
|
+
"included2": "@included"
|
2135
|
+
},
|
2136
|
+
"included1": [
|
2137
|
+
{"prop": "value1"},
|
2138
|
+
{"prop": "value2"}
|
2139
|
+
]
|
2140
|
+
}),
|
2141
|
+
input: %([{
|
2142
|
+
"@included": [
|
2143
|
+
{"http://example.org/prop": [{"@value": "value1"}]},
|
2144
|
+
{"http://example.org/prop": [{"@value": "value2"}]}
|
2145
|
+
]
|
2146
|
+
}])
|
2147
|
+
},
|
2148
|
+
"Included containing @included": {
|
2149
|
+
output: %({
|
2150
|
+
"@context": {
|
2151
|
+
"@version": 1.1,
|
2152
|
+
"@vocab": "http://example.org/"
|
2153
|
+
},
|
2154
|
+
"prop": "value",
|
2155
|
+
"@included": {
|
2156
|
+
"prop": "value2",
|
2157
|
+
"@included": {
|
2158
|
+
"prop": "value3"
|
2159
|
+
}
|
2160
|
+
}
|
2161
|
+
}),
|
2162
|
+
input: %([{
|
2163
|
+
"http://example.org/prop": [{"@value": "value"}],
|
2164
|
+
"@included": [{
|
2165
|
+
"http://example.org/prop": [{"@value": "value2"}],
|
2166
|
+
"@included": [{
|
2167
|
+
"http://example.org/prop": [{"@value": "value3"}]
|
2168
|
+
}]
|
2169
|
+
}]
|
2170
|
+
}])
|
2171
|
+
},
|
2172
|
+
"Property value with @included": {
|
2173
|
+
output: %({
|
2174
|
+
"@context": {
|
2175
|
+
"@version": 1.1,
|
2176
|
+
"@vocab": "http://example.org/"
|
2177
|
+
},
|
2178
|
+
"prop": {
|
2179
|
+
"@type": "Foo",
|
2180
|
+
"@included": {
|
2181
|
+
"@type": "Bar"
|
2182
|
+
}
|
2183
|
+
}
|
2184
|
+
}),
|
2185
|
+
input: %([{
|
2186
|
+
"http://example.org/prop": [{
|
2187
|
+
"@type": ["http://example.org/Foo"],
|
2188
|
+
"@included": [{
|
2189
|
+
"@type": ["http://example.org/Bar"]
|
2190
|
+
}]
|
2191
|
+
}]
|
2192
|
+
}])
|
2193
|
+
},
|
2194
|
+
}.each do |title, params|
|
2195
|
+
it(title) {run_compact(params)}
|
2196
|
+
end
|
2197
|
+
end
|
2198
|
+
|
1504
2199
|
context "@nest" do
|
1505
2200
|
{
|
1506
2201
|
"Indexes to @nest for property with @nest" => {
|
@@ -1895,7 +2590,7 @@ describe JSON::LD::API do
|
|
1895
2590
|
"c": "C in example"
|
1896
2591
|
}),
|
1897
2592
|
},
|
1898
|
-
"Raises InvalidTermDefinition if processingMode is
|
2593
|
+
"Raises InvalidTermDefinition if processingMode is 1.0" => {
|
1899
2594
|
input: %([{
|
1900
2595
|
"http://example/foo": [{"http://example.org/bar": [{"@value": "baz"}]}]
|
1901
2596
|
}]),
|
@@ -1903,10 +2598,59 @@ describe JSON::LD::API do
|
|
1903
2598
|
"@vocab": "http://example/",
|
1904
2599
|
"foo": {"@context": {"bar": "http://example.org/bar"}}
|
1905
2600
|
}),
|
1906
|
-
processingMode:
|
2601
|
+
processingMode: 'json-ld-1.0',
|
1907
2602
|
validate: true,
|
1908
2603
|
exception: JSON::LD::JsonLdError::InvalidTermDefinition
|
1909
2604
|
},
|
2605
|
+
"Scoped on id map": {
|
2606
|
+
output: %({
|
2607
|
+
"@context": {
|
2608
|
+
"@version": 1.1,
|
2609
|
+
"schema": "http://schema.org/",
|
2610
|
+
"name": "schema:name",
|
2611
|
+
"body": "schema:articleBody",
|
2612
|
+
"words": "schema:wordCount",
|
2613
|
+
"post": {
|
2614
|
+
"@id": "schema:blogPost",
|
2615
|
+
"@container": "@id",
|
2616
|
+
"@context": {
|
2617
|
+
"@base": "http://example.com/posts/"
|
2618
|
+
}
|
2619
|
+
}
|
2620
|
+
},
|
2621
|
+
"@id": "http://example.com/",
|
2622
|
+
"@type": "schema:Blog",
|
2623
|
+
"name": "World Financial News",
|
2624
|
+
"post": {
|
2625
|
+
"1/en": {
|
2626
|
+
"body": "World commodities were up today with heavy trading of crude oil...",
|
2627
|
+
"words": 1539
|
2628
|
+
},
|
2629
|
+
"1/de": {
|
2630
|
+
"body": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl...",
|
2631
|
+
"words": 1204
|
2632
|
+
}
|
2633
|
+
}
|
2634
|
+
}),
|
2635
|
+
input: %([{
|
2636
|
+
"@id": "http://example.com/",
|
2637
|
+
"@type": ["http://schema.org/Blog"],
|
2638
|
+
"http://schema.org/name": [{"@value": "World Financial News"}],
|
2639
|
+
"http://schema.org/blogPost": [{
|
2640
|
+
"@id": "http://example.com/posts/1/en",
|
2641
|
+
"http://schema.org/articleBody": [
|
2642
|
+
{"@value": "World commodities were up today with heavy trading of crude oil..."}
|
2643
|
+
],
|
2644
|
+
"http://schema.org/wordCount": [{"@value": 1539}]
|
2645
|
+
}, {
|
2646
|
+
"@id": "http://example.com/posts/1/de",
|
2647
|
+
"http://schema.org/articleBody": [
|
2648
|
+
{"@value": "Die Werte an Warenbörsen stiegen im Sog eines starken Handels von Rohöl..."}
|
2649
|
+
],
|
2650
|
+
"http://schema.org/wordCount": [{"@value": 1204}]
|
2651
|
+
}]
|
2652
|
+
}])
|
2653
|
+
},
|
1910
2654
|
}.each_pair do |title, params|
|
1911
2655
|
it(title) {run_compact({processingMode: "json-ld-1.1"}.merge(params))}
|
1912
2656
|
end
|
@@ -1981,7 +2725,7 @@ describe JSON::LD::API do
|
|
1981
2725
|
"a": {"type": "Foo", "bar": "baz"}
|
1982
2726
|
}),
|
1983
2727
|
},
|
1984
|
-
"deep @context
|
2728
|
+
"deep @context does not affect nested nodes" => {
|
1985
2729
|
input: %([
|
1986
2730
|
{
|
1987
2731
|
"@type": ["http://example/Foo"],
|
@@ -2000,7 +2744,7 @@ describe JSON::LD::API do
|
|
2000
2744
|
"Foo": {"@context": {"baz": {"@type": "@vocab"}}}
|
2001
2745
|
},
|
2002
2746
|
"@type": "Foo",
|
2003
|
-
"bar": {"baz": "buzz"}
|
2747
|
+
"bar": {"baz": {"@id": "http://example/buzz"}}
|
2004
2748
|
}),
|
2005
2749
|
},
|
2006
2750
|
"scoped context layers on intemediate contexts" => {
|
@@ -2073,7 +2817,7 @@ describe JSON::LD::API do
|
|
2073
2817
|
}
|
2074
2818
|
})
|
2075
2819
|
},
|
2076
|
-
"Raises InvalidTermDefinition if processingMode is
|
2820
|
+
"Raises InvalidTermDefinition if processingMode is 1.0" => {
|
2077
2821
|
input: %([
|
2078
2822
|
{
|
2079
2823
|
"http://example/a": [{
|
@@ -2086,7 +2830,7 @@ describe JSON::LD::API do
|
|
2086
2830
|
"@vocab": "http://example/",
|
2087
2831
|
"Foo": {"@context": {"bar": "http://example.org/bar"}}
|
2088
2832
|
}),
|
2089
|
-
processingMode:
|
2833
|
+
processingMode: 'json-ld-1.0',
|
2090
2834
|
validate: true,
|
2091
2835
|
exception: JSON::LD::JsonLdError::InvalidTermDefinition
|
2092
2836
|
},
|
@@ -2227,16 +2971,231 @@ describe JSON::LD::API do
|
|
2227
2971
|
end
|
2228
2972
|
end
|
2229
2973
|
|
2974
|
+
context "html" do
|
2975
|
+
{
|
2976
|
+
"Compacts embedded JSON-LD script element": {
|
2977
|
+
input: %(
|
2978
|
+
<html>
|
2979
|
+
<head>
|
2980
|
+
<script type="application/ld+json">
|
2981
|
+
{
|
2982
|
+
"@context": {
|
2983
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
2984
|
+
},
|
2985
|
+
"foo": [{"@value": "bar"}]
|
2986
|
+
}
|
2987
|
+
</script>
|
2988
|
+
</head>
|
2989
|
+
</html>),
|
2990
|
+
context: %({"foo": {"@id": "http://example.com/foo", "@container": "@list"}}),
|
2991
|
+
output: %({
|
2992
|
+
"@context": {
|
2993
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
2994
|
+
},
|
2995
|
+
"foo": ["bar"]
|
2996
|
+
})
|
2997
|
+
},
|
2998
|
+
"Compacts first script element": {
|
2999
|
+
input: %(
|
3000
|
+
<html>
|
3001
|
+
<head>
|
3002
|
+
<script type="application/ld+json">
|
3003
|
+
{
|
3004
|
+
"@context": {
|
3005
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
3006
|
+
},
|
3007
|
+
"foo": [{"@value": "bar"}]
|
3008
|
+
}
|
3009
|
+
</script>
|
3010
|
+
<script type="application/ld+json">
|
3011
|
+
{
|
3012
|
+
"@context": {"ex": "http://example.com/"},
|
3013
|
+
"@graph": [
|
3014
|
+
{"ex:foo": {"@value": "foo"}},
|
3015
|
+
{"ex:bar": {"@value": "bar"}}
|
3016
|
+
]
|
3017
|
+
}
|
3018
|
+
</script>
|
3019
|
+
</head>
|
3020
|
+
</html>),
|
3021
|
+
context: %({"foo": {"@id": "http://example.com/foo", "@container": "@list"}}),
|
3022
|
+
output: %({
|
3023
|
+
"@context": {
|
3024
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
3025
|
+
},
|
3026
|
+
"foo": ["bar"]
|
3027
|
+
})
|
3028
|
+
},
|
3029
|
+
"Compacts targeted script element": {
|
3030
|
+
input: %(
|
3031
|
+
<html>
|
3032
|
+
<head>
|
3033
|
+
<script id="first" type="application/ld+json">
|
3034
|
+
{
|
3035
|
+
"@context": {
|
3036
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
3037
|
+
},
|
3038
|
+
"foo": [{"@value": "bar"}]
|
3039
|
+
}
|
3040
|
+
</script>
|
3041
|
+
<script id="second" type="application/ld+json">
|
3042
|
+
{
|
3043
|
+
"@context": {"ex": "http://example.com/"},
|
3044
|
+
"@graph": [
|
3045
|
+
{"ex:foo": {"@value": "foo"}},
|
3046
|
+
{"ex:bar": {"@value": "bar"}}
|
3047
|
+
]
|
3048
|
+
}
|
3049
|
+
</script>
|
3050
|
+
</head>
|
3051
|
+
</html>),
|
3052
|
+
context: %({"ex": "http://example.com/"}),
|
3053
|
+
output: %({
|
3054
|
+
"@context": {"ex": "http://example.com/"},
|
3055
|
+
"@graph": [
|
3056
|
+
{"ex:foo": "foo"},
|
3057
|
+
{"ex:bar": "bar"}
|
3058
|
+
]
|
3059
|
+
}),
|
3060
|
+
base: "http://example.org/doc#second"
|
3061
|
+
},
|
3062
|
+
"Compacts all script elements with extractAllScripts option": {
|
3063
|
+
input: %(
|
3064
|
+
<html>
|
3065
|
+
<head>
|
3066
|
+
<script type="application/ld+json">
|
3067
|
+
{
|
3068
|
+
"@context": {
|
3069
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
3070
|
+
},
|
3071
|
+
"foo": [{"@value": "bar"}]
|
3072
|
+
}
|
3073
|
+
</script>
|
3074
|
+
<script type="application/ld+json">
|
3075
|
+
{
|
3076
|
+
"@context": {"ex": "http://example.com/"},
|
3077
|
+
"@graph": [
|
3078
|
+
{"ex:foo": {"@value": "foo"}},
|
3079
|
+
{"ex:bar": {"@value": "bar"}}
|
3080
|
+
]
|
3081
|
+
}
|
3082
|
+
</script>
|
3083
|
+
</head>
|
3084
|
+
</html>),
|
3085
|
+
context: %({
|
3086
|
+
"ex": "http://example.com/",
|
3087
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
3088
|
+
}),
|
3089
|
+
output: %({
|
3090
|
+
"@context": {
|
3091
|
+
"ex": "http://example.com/",
|
3092
|
+
"foo": {"@id": "http://example.com/foo", "@container": "@list"}
|
3093
|
+
},
|
3094
|
+
"@graph": [
|
3095
|
+
{"foo": ["bar"]},
|
3096
|
+
{
|
3097
|
+
"@graph": [
|
3098
|
+
{"ex:foo": "foo"},
|
3099
|
+
{"ex:bar": "bar"}
|
3100
|
+
]
|
3101
|
+
}
|
3102
|
+
]
|
3103
|
+
}),
|
3104
|
+
extractAllScripts: true
|
3105
|
+
},
|
3106
|
+
}.each do |title, params|
|
3107
|
+
it(title) do
|
3108
|
+
params[:input] = StringIO.new(params[:input])
|
3109
|
+
params[:input].send(:define_singleton_method, :content_type) {"text/html"}
|
3110
|
+
run_compact params.merge(validate: true)
|
3111
|
+
end
|
3112
|
+
end
|
3113
|
+
end
|
3114
|
+
|
3115
|
+
|
3116
|
+
context "problem cases" do
|
3117
|
+
{
|
3118
|
+
"issue json-ld-framing#64": {
|
3119
|
+
input: %({
|
3120
|
+
"@context": {
|
3121
|
+
"@version": 1.1,
|
3122
|
+
"@vocab": "http://example.org/vocab#"
|
3123
|
+
},
|
3124
|
+
"@id": "http://example.org/1",
|
3125
|
+
"@type": "HumanMadeObject",
|
3126
|
+
"produced_by": {
|
3127
|
+
"@type": "Production",
|
3128
|
+
"_label": "Top Production",
|
3129
|
+
"part": {
|
3130
|
+
"@type": "Production",
|
3131
|
+
"_label": "Test Part"
|
3132
|
+
}
|
3133
|
+
}
|
3134
|
+
}),
|
3135
|
+
context: %({
|
3136
|
+
"@version": 1.1,
|
3137
|
+
"@vocab": "http://example.org/vocab#",
|
3138
|
+
"Production": {
|
3139
|
+
"@context": {
|
3140
|
+
"part": {
|
3141
|
+
"@type": "@id",
|
3142
|
+
"@container": "@set"
|
3143
|
+
}
|
3144
|
+
}
|
3145
|
+
}
|
3146
|
+
}),
|
3147
|
+
output: %({
|
3148
|
+
"@context": {
|
3149
|
+
"@version": 1.1,
|
3150
|
+
"@vocab": "http://example.org/vocab#",
|
3151
|
+
"Production": {
|
3152
|
+
"@context": {
|
3153
|
+
"part": {
|
3154
|
+
"@type": "@id",
|
3155
|
+
"@container": "@set"
|
3156
|
+
}
|
3157
|
+
}
|
3158
|
+
}
|
3159
|
+
},
|
3160
|
+
"@id": "http://example.org/1",
|
3161
|
+
"@type": "HumanMadeObject",
|
3162
|
+
"produced_by": {
|
3163
|
+
"@type": "Production",
|
3164
|
+
"part": [{
|
3165
|
+
"@type": "Production",
|
3166
|
+
"_label": "Test Part"
|
3167
|
+
}],
|
3168
|
+
"_label": "Top Production"
|
3169
|
+
}
|
3170
|
+
}),
|
3171
|
+
processingMode: "json-ld-1.1"
|
3172
|
+
}
|
3173
|
+
}.each do |title, params|
|
3174
|
+
it title do
|
3175
|
+
run_compact(params)
|
3176
|
+
end
|
3177
|
+
end
|
3178
|
+
end
|
3179
|
+
|
2230
3180
|
def run_compact(params)
|
2231
3181
|
input, output, context = params[:input], params[:output], params[:context]
|
3182
|
+
params[:base] ||= nil
|
3183
|
+
context ||= output # Since it will have the context
|
2232
3184
|
input = ::JSON.parse(input) if input.is_a?(String)
|
2233
3185
|
output = ::JSON.parse(output) if output.is_a?(String)
|
2234
3186
|
context = ::JSON.parse(context) if context.is_a?(String)
|
3187
|
+
context = context['@context'] if context.has_key?('@context')
|
2235
3188
|
pending params.fetch(:pending, "test implementation") unless input
|
2236
3189
|
if params[:exception]
|
2237
|
-
expect {JSON::LD::API.compact(input, context,
|
3190
|
+
expect {JSON::LD::API.compact(input, context, logger: logger, **params)}.to raise_error(params[:exception])
|
2238
3191
|
else
|
2239
|
-
jld =
|
3192
|
+
jld = nil
|
3193
|
+
if params[:write]
|
3194
|
+
expect{jld = JSON::LD::API.compact(input, context, logger: logger, **params)}.to write(params[:write]).to(:error)
|
3195
|
+
else
|
3196
|
+
expect{jld = JSON::LD::API.compact(input, context, logger: logger, **params)}.not_to write.to(:error)
|
3197
|
+
end
|
3198
|
+
|
2240
3199
|
expect(jld).to produce_jsonld(output, logger)
|
2241
3200
|
|
2242
3201
|
# Compare expanded jld/output too to make sure list values remain ordered
|