json-ld 3.1.4 → 3.1.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +131 -48
- data/VERSION +1 -1
- data/bin/jsonld +31 -32
- data/lib/json/ld.rb +5 -2
- data/lib/json/ld/api.rb +35 -16
- data/lib/json/ld/compact.rb +41 -29
- data/lib/json/ld/conneg.rb +1 -1
- data/lib/json/ld/context.rb +51 -59
- data/lib/json/ld/expand.rb +72 -16
- data/lib/json/ld/extensions.rb +4 -4
- data/lib/json/ld/flatten.rb +137 -9
- data/lib/json/ld/format.rb +28 -8
- data/lib/json/ld/frame.rb +8 -8
- data/lib/json/ld/from_rdf.rb +46 -16
- data/lib/json/ld/reader.rb +2 -1
- data/lib/json/ld/streaming_reader.rb +5 -5
- data/lib/json/ld/streaming_writer.rb +4 -4
- data/lib/json/ld/to_rdf.rb +11 -7
- data/lib/json/ld/utils.rb +13 -13
- data/lib/json/ld/writer.rb +12 -5
- data/spec/api_spec.rb +1 -1
- data/spec/compact_spec.rb +207 -3
- data/spec/context_spec.rb +0 -2
- data/spec/expand_spec.rb +631 -0
- data/spec/flatten_spec.rb +517 -1
- data/spec/from_rdf_spec.rb +181 -0
- data/spec/matchers.rb +1 -1
- data/spec/rdfstar_spec.rb +25 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/suite_flatten_spec.rb +4 -0
- data/spec/suite_frame_spec.rb +7 -0
- data/spec/suite_helper.rb +13 -7
- data/spec/suite_to_rdf_spec.rb +1 -0
- data/spec/to_rdf_spec.rb +209 -3
- data/spec/writer_spec.rb +193 -0
- metadata +66 -64
data/lib/json/ld.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
# frozen_string_literal: true
|
3
3
|
$:.unshift(File.expand_path("../ld", __FILE__))
|
4
|
-
require 'rdf' # @see
|
4
|
+
require 'rdf' # @see https://rubygems.org/gems/rdf
|
5
5
|
require 'multi_json'
|
6
6
|
require 'set'
|
7
7
|
|
@@ -19,7 +19,7 @@ module JSON
|
|
19
19
|
# end
|
20
20
|
# end
|
21
21
|
#
|
22
|
-
# @see
|
22
|
+
# @see https://rubygems.org/gems/rdf
|
23
23
|
# @see http://www.w3.org/TR/REC-rdf-syntax/
|
24
24
|
#
|
25
25
|
# @author [Gregg Kellogg](http://greggkellogg.net/)
|
@@ -47,6 +47,7 @@ module JSON
|
|
47
47
|
DEFAULT_CONTEXT = "http://schema.org"
|
48
48
|
|
49
49
|
KEYWORDS = Set.new(%w(
|
50
|
+
@annotation
|
50
51
|
@base
|
51
52
|
@container
|
52
53
|
@context
|
@@ -116,6 +117,7 @@ module JSON
|
|
116
117
|
class CollidingKeywords < JsonLdError; @code = "colliding keywords"; end
|
117
118
|
class ConflictingIndexes < JsonLdError; @code = "conflicting indexes"; end
|
118
119
|
class CyclicIRIMapping < JsonLdError; @code = "cyclic IRI mapping"; end
|
120
|
+
class InvalidAnnotation < JsonLdError; @code = "invalid annotation"; end
|
119
121
|
class InvalidBaseIRI < JsonLdError; @code = "invalid base IRI"; end
|
120
122
|
class InvalidContainerMapping < JsonLdError; @code = "invalid container mapping"; end
|
121
123
|
class InvalidContextEntry < JsonLdError; @code = "invalid context entry"; end
|
@@ -137,6 +139,7 @@ module JSON
|
|
137
139
|
class InvalidNestValue < JsonLdError; @code = "invalid @nest value"; end
|
138
140
|
class InvalidPrefixValue < JsonLdError; @code = "invalid @prefix value"; end
|
139
141
|
class InvalidPropagateValue < JsonLdError; @code = "invalid @propagate value"; end
|
142
|
+
class InvalidEmbeddedNode < JsonLdError; @code = "invalid embedded node"; end
|
140
143
|
class InvalidRemoteContext < JsonLdError; @code = "invalid remote context"; end
|
141
144
|
class InvalidReverseProperty < JsonLdError; @code = "invalid reverse property"; end
|
142
145
|
class InvalidReversePropertyMap < JsonLdError; @code = "invalid reverse property map"; end
|
data/lib/json/ld/api.rb
CHANGED
@@ -89,6 +89,8 @@ module JSON::LD
|
|
89
89
|
# @option options [String] :processingMode
|
90
90
|
# Processing mode, json-ld-1.0 or json-ld-1.1.
|
91
91
|
# If `processingMode` is not specified, a mode of `json-ld-1.0` or `json-ld-1.1` is set, the context used for `expansion` or `compaction`.
|
92
|
+
# @option options [Boolean] rdfstar (false)
|
93
|
+
# support parsing JSON-LD-star statement resources.
|
92
94
|
# @option options [Boolean] :rename_bnodes (true)
|
93
95
|
# Rename bnodes as part of expansion, or keep them the same.
|
94
96
|
# @option options [Boolean] :unique_bnodes (false)
|
@@ -100,13 +102,15 @@ module JSON::LD
|
|
100
102
|
# @yield [api]
|
101
103
|
# @yieldparam [API]
|
102
104
|
# @raise [JsonLdError]
|
103
|
-
def initialize(input, context,
|
105
|
+
def initialize(input, context, **options, &block)
|
104
106
|
@options = {
|
105
107
|
compactArrays: true,
|
106
108
|
ordered: false,
|
107
109
|
extractAllScripts: false,
|
110
|
+
rename_bnodes: true,
|
111
|
+
unique_bnodes: false,
|
108
112
|
}.merge(options)
|
109
|
-
@namer = unique_bnodes ? BlankNodeUniqer.new : (rename_bnodes ? BlankNodeNamer.new("b") : BlankNodeMapper.new)
|
113
|
+
@namer = @options[:unique_bnodes] ? BlankNodeUniqer.new : (@options[:rename_bnodes] ? BlankNodeNamer.new("b") : BlankNodeMapper.new)
|
110
114
|
|
111
115
|
@options[:base] = RDF::URI(@options[:base]) if @options[:base] && !@options[:base].is_a?(RDF::URI)
|
112
116
|
# For context via Link header
|
@@ -200,9 +204,9 @@ module JSON::LD
|
|
200
204
|
# The JSON-LD object to copy and perform the compaction upon.
|
201
205
|
# @param [String, #read, Hash, Array, JSON::LD::Context] context
|
202
206
|
# The base context to use when compacting the input.
|
207
|
+
# @param [Boolean] expanded (false) Input is already expanded
|
203
208
|
# @param [Hash{Symbol => Object}] options
|
204
209
|
# @option options (see #initialize)
|
205
|
-
# @option options [Boolean] :expanded Input is already expanded
|
206
210
|
# @yield jsonld
|
207
211
|
# @yieldparam [Hash] jsonld
|
208
212
|
# The compacted JSON-LD document
|
@@ -246,9 +250,11 @@ module JSON::LD
|
|
246
250
|
# The JSON-LD object or array of JSON-LD objects to flatten or an IRI referencing the JSON-LD document to flatten.
|
247
251
|
# @param [String, #read, Hash, Array, JSON::LD::EvaluationContext] context
|
248
252
|
# An optional external context to use additionally to the context embedded in input when expanding the input.
|
253
|
+
# @param [Boolean] expanded (false) Input is already expanded
|
249
254
|
# @param [Hash{Symbol => Object}] options
|
250
255
|
# @option options (see #initialize)
|
251
|
-
# @option options [Boolean] :
|
256
|
+
# @option options [Boolean] :createAnnotations
|
257
|
+
# Unfold embedded nodes which can be represented using `@annotation`.
|
252
258
|
# @yield jsonld
|
253
259
|
# @yieldparam [Hash] jsonld
|
254
260
|
# The flattened JSON-LD document
|
@@ -273,10 +279,20 @@ module JSON::LD
|
|
273
279
|
API.new(expanded_input, context, no_default_base: true, **options) do
|
274
280
|
log_debug(".flatten") {"expanded input: #{value.to_json(JSON_STATE) rescue 'malformed json'}"}
|
275
281
|
|
282
|
+
# Rename blank nodes recusively. Note that this does not create new blank node identifiers where none exist, which is performed in the node map generation algorithm.
|
283
|
+
@value = rename_bnodes(@value) if @options[:rename_bnodes]
|
284
|
+
|
276
285
|
# Initialize node map to a JSON object consisting of a single member whose key is @default and whose value is an empty JSON object.
|
277
286
|
graph_maps = {'@default' => {}}
|
278
287
|
create_node_map(value, graph_maps)
|
279
288
|
|
289
|
+
# If create annotations flag is set, then update each node map in graph maps with the result of calling the create annotations algorithm.
|
290
|
+
if options[:createAnnotations]
|
291
|
+
graph_maps.values.each do |node_map|
|
292
|
+
create_annotations(node_map)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
280
296
|
default_graph = graph_maps['@default']
|
281
297
|
graph_maps.keys.opt_sort(ordered: @options[:ordered]).each do |graph_name|
|
282
298
|
next if graph_name == '@default'
|
@@ -295,7 +311,7 @@ module JSON::LD
|
|
295
311
|
if context && !flattened.empty?
|
296
312
|
# Otherwise, return the result of compacting flattened according the Compaction algorithm passing context ensuring that the compaction result uses the @graph keyword (or its alias) at the top-level, even if the context is empty or if there is only one element to put in the @graph array. This ensures that the returned document has a deterministic structure.
|
297
313
|
compacted = as_array(compact(flattened))
|
298
|
-
kwgraph = self.context.compact_iri('@graph')
|
314
|
+
kwgraph = self.context.compact_iri('@graph', vocab: true)
|
299
315
|
flattened = self.context.
|
300
316
|
serialize(provided_context: context).
|
301
317
|
merge(kwgraph => compacted)
|
@@ -314,6 +330,7 @@ module JSON::LD
|
|
314
330
|
# The JSON-LD object to copy and perform the framing on.
|
315
331
|
# @param [String, #read, Hash, Array] frame
|
316
332
|
# The frame to use when re-arranging the data.
|
333
|
+
# @param [Boolean] expanded (false) Input is already expanded
|
317
334
|
# @option options (see #initialize)
|
318
335
|
# @option options ['@always', '@link', '@once', '@never'] :embed ('@once')
|
319
336
|
# a flag specifying that objects should be directly embedded in the output, instead of being referred to by their IRI.
|
@@ -323,7 +340,6 @@ module JSON::LD
|
|
323
340
|
# A flag specifying that all properties present in the input frame must either have a default value or be present in the JSON-LD input for the frame to match.
|
324
341
|
# @option options [Boolean] :omitDefault (false)
|
325
342
|
# a flag specifying that properties that are missing from the JSON-LD input should be omitted from the output.
|
326
|
-
# @option options [Boolean] :expanded Input is already expanded
|
327
343
|
# @option options [Boolean] :pruneBlankNodeIdentifiers (true) removes blank node identifiers that are only used once.
|
328
344
|
# @option options [Boolean] :omitGraph does not use `@graph` at top level unless necessary to describe multiple objects, defaults to `true` if processingMode is 1.1, otherwise `false`.
|
329
345
|
# @yield jsonld
|
@@ -389,10 +405,13 @@ module JSON::LD
|
|
389
405
|
end
|
390
406
|
|
391
407
|
# Set omitGraph option, if not present, based on processingMode
|
392
|
-
unless options.
|
408
|
+
unless options.key?(:omitGraph)
|
393
409
|
options[:omitGraph] = context.processingMode('json-ld-1.1')
|
394
410
|
end
|
395
411
|
|
412
|
+
# Rename blank nodes recusively. Note that this does not create new blank node identifiers where none exist, which is performed in the node map generation algorithm.
|
413
|
+
@value = rename_bnodes(@value)
|
414
|
+
|
396
415
|
# Get framing nodes from expanded input, replacing Blank Node identifiers as necessary
|
397
416
|
create_node_map(value, framing_state[:graphMap], active_graph: '@default')
|
398
417
|
|
@@ -413,7 +432,7 @@ module JSON::LD
|
|
413
432
|
frame(framing_state, framing_state[:subjects].keys.opt_sort(ordered: @options[:ordered]), (expanded_frame.first || {}), parent: result, **options)
|
414
433
|
|
415
434
|
# Default to based on processinMode
|
416
|
-
if !options.
|
435
|
+
if !options.key?(:pruneBlankNodeIdentifiers)
|
417
436
|
options[:pruneBlankNodeIdentifiers] = context.processingMode('json-ld-1.1')
|
418
437
|
end
|
419
438
|
|
@@ -438,7 +457,7 @@ module JSON::LD
|
|
438
457
|
result = if !compacted.is_a?(Array)
|
439
458
|
compacted
|
440
459
|
else
|
441
|
-
kwgraph = context.compact_iri('@graph')
|
460
|
+
kwgraph = context.compact_iri('@graph', vocab: true)
|
442
461
|
{kwgraph => compacted}
|
443
462
|
end
|
444
463
|
# Only add context if one was provided
|
@@ -456,10 +475,10 @@ module JSON::LD
|
|
456
475
|
#
|
457
476
|
# @param [String, #read, Hash, Array] input
|
458
477
|
# The JSON-LD object to process when outputting statements.
|
478
|
+
# @param [Boolean] expanded (false) Input is already expanded
|
459
479
|
# @option options (see #initialize)
|
460
480
|
# @option options [Boolean] :produceGeneralizedRdf (false)
|
461
481
|
# If true, output will include statements having blank node predicates, otherwise they are dropped.
|
462
|
-
# @option options [Boolean] :expanded Input is already expanded
|
463
482
|
# @raise [JsonLdError]
|
464
483
|
# @yield statement
|
465
484
|
# @yieldparam [RDF::Statement] statement
|
@@ -468,7 +487,7 @@ module JSON::LD
|
|
468
487
|
unless block_given?
|
469
488
|
results = []
|
470
489
|
results.extend(RDF::Enumerable)
|
471
|
-
self.toRdf(input, **options) do |stmt|
|
490
|
+
self.toRdf(input, expanded: expanded, **options) do |stmt|
|
472
491
|
results << stmt
|
473
492
|
end
|
474
493
|
return results
|
@@ -478,16 +497,16 @@ module JSON::LD
|
|
478
497
|
extractAllScripts: true,
|
479
498
|
}.merge(options)
|
480
499
|
|
481
|
-
#
|
482
|
-
|
500
|
+
# Flatten input to simplify processing
|
501
|
+
flattened_input = API.flatten(input, nil, expanded: expanded, ordered: false, **options)
|
483
502
|
|
484
|
-
API.new(
|
503
|
+
API.new(flattened_input, nil, **options) do
|
485
504
|
# 1) Perform the Expansion Algorithm on the JSON-LD input.
|
486
505
|
# This removes any existing context to allow the given context to be cleanly applied.
|
487
|
-
log_debug(".toRdf") {"
|
506
|
+
log_debug(".toRdf") {"flattened input: #{flattened_input.to_json(JSON_STATE) rescue 'malformed json'}"}
|
488
507
|
|
489
508
|
# Recurse through input
|
490
|
-
|
509
|
+
flattened_input.each do |node|
|
491
510
|
item_to_rdf(node) do |statement|
|
492
511
|
next if statement.predicate.node? && !options[:produceGeneralizedRdf]
|
493
512
|
|
data/lib/json/ld/compact.rb
CHANGED
@@ -19,12 +19,9 @@ module JSON::LD
|
|
19
19
|
# @return [Array, Hash]
|
20
20
|
def compact(element,
|
21
21
|
base: nil,
|
22
|
-
property: nil
|
23
|
-
|
24
|
-
|
25
|
-
#else
|
26
|
-
# log_debug("compact") {"property: #{property.inspect}"}
|
27
|
-
#end
|
22
|
+
property: nil,
|
23
|
+
log_depth: nil)
|
24
|
+
log_debug("compact", depth: log_depth.to_i) {"element: #{element.inspect}, ec: #{context.inspect}"}
|
28
25
|
|
29
26
|
# If the term definition for active property itself contains a context, use that for compacting values.
|
30
27
|
input_context = self.context
|
@@ -33,7 +30,7 @@ module JSON::LD
|
|
33
30
|
when Array
|
34
31
|
#log_debug("") {"Array #{element.inspect}"}
|
35
32
|
result = element.map do |item|
|
36
|
-
compact(item, base: base, property: property)
|
33
|
+
compact(item, base: base, property: property, log_depth: log_depth.to_i + 1)
|
37
34
|
end.compact
|
38
35
|
|
39
36
|
# If element has a single member and the active property has no
|
@@ -41,10 +38,10 @@ module JSON::LD
|
|
41
38
|
# member; otherwise the compacted value is element
|
42
39
|
if result.length == 1 &&
|
43
40
|
!context.as_array?(property) && @options[:compactArrays]
|
44
|
-
|
41
|
+
log_debug("=> extract single element", depth: log_depth.to_i) {result.first.inspect}
|
45
42
|
result.first
|
46
43
|
else
|
47
|
-
|
44
|
+
log_debug("=> array result", depth: log_depth.to_i) {result.inspect}
|
48
45
|
result
|
49
46
|
end
|
50
47
|
when Hash
|
@@ -55,6 +52,7 @@ module JSON::LD
|
|
55
52
|
|
56
53
|
# Revert any previously type-scoped (non-preserved) context
|
57
54
|
if context.previous_context && !element.key?('@value') && element.keys != %w(@id)
|
55
|
+
log_debug("revert ec", depth: log_depth.to_i) {"previous context: #{context.previous_context.inspect}"}
|
58
56
|
self.context = context.previous_context
|
59
57
|
end
|
60
58
|
|
@@ -63,12 +61,13 @@ module JSON::LD
|
|
63
61
|
if td && !td.context.nil?
|
64
62
|
self.context = context.parse(td.context,
|
65
63
|
override_protected: true)
|
64
|
+
log_debug("prop-scoped", depth: log_depth.to_i) {"context: #{self.context.inspect}"}
|
66
65
|
end
|
67
66
|
|
68
|
-
if element.key?('@id') || element.key?('@value')
|
67
|
+
if (element.key?('@id') || element.key?('@value')) && !element.key?('@annotation')
|
69
68
|
result = context.compact_value(property, element, base: @options[:base])
|
70
69
|
if !result.is_a?(Hash) || context.coerce(property) == '@json'
|
71
|
-
|
70
|
+
log_debug("", depth: log_depth.to_i) {"=> scalar result: #{result.inspect}"}
|
72
71
|
return result
|
73
72
|
end
|
74
73
|
end
|
@@ -76,7 +75,8 @@ module JSON::LD
|
|
76
75
|
# If expanded property is @list and we're contained within a list container, recursively compact this item to an array
|
77
76
|
if list?(element) && context.container(property).include?('@list')
|
78
77
|
return compact(element['@list'], base: base,
|
79
|
-
property: property
|
78
|
+
property: property,
|
79
|
+
log_depth: log_depth.to_i + 1)
|
80
80
|
end
|
81
81
|
|
82
82
|
inside_reverse = property == '@reverse'
|
@@ -90,15 +90,23 @@ module JSON::LD
|
|
90
90
|
each do |term|
|
91
91
|
term_context = input_context.term_definitions[term].context if input_context.term_definitions[term]
|
92
92
|
self.context = context.parse(term_context, propagate: false) unless term_context.nil?
|
93
|
+
log_debug("type-scoped", depth: log_depth.to_i) {"context: #{self.context.inspect}"}
|
93
94
|
end
|
94
95
|
|
95
96
|
element.keys.opt_sort(ordered: @options[:ordered]).each do |expanded_property|
|
96
97
|
expanded_value = element[expanded_property]
|
97
|
-
|
98
|
+
log_debug("", depth: log_depth.to_i) {"#{expanded_property}: #{expanded_value.inspect}"}
|
98
99
|
|
99
100
|
if expanded_property == '@id'
|
100
|
-
compacted_value =
|
101
|
-
|
101
|
+
compacted_value = as_array(expanded_value).map do |expanded_id|
|
102
|
+
if node?(expanded_id) && @options[:rdfstar]
|
103
|
+
# This can only really happen for valid RDF-star
|
104
|
+
compact(expanded_id, base: base,
|
105
|
+
property: '@id',
|
106
|
+
log_depth: log_depth.to_i + 1)
|
107
|
+
else
|
108
|
+
context.compact_iri(expanded_id, base: @options[:base])
|
109
|
+
end
|
102
110
|
end
|
103
111
|
|
104
112
|
kw_alias = context.compact_iri('@id', vocab: true)
|
@@ -124,8 +132,9 @@ module JSON::LD
|
|
124
132
|
|
125
133
|
if expanded_property == '@reverse'
|
126
134
|
compacted_value = compact(expanded_value, base: base,
|
127
|
-
property: '@reverse'
|
128
|
-
|
135
|
+
property: '@reverse',
|
136
|
+
log_depth: log_depth.to_i + 1)
|
137
|
+
log_debug("@reverse", depth: log_depth.to_i) {"compacted_value: #{compacted_value.inspect}"}
|
129
138
|
# handle double-reversed properties
|
130
139
|
compacted_value.each do |prop, value|
|
131
140
|
if context.reverse?(prop)
|
@@ -136,8 +145,8 @@ module JSON::LD
|
|
136
145
|
end
|
137
146
|
|
138
147
|
unless compacted_value.empty?
|
139
|
-
al = context.compact_iri('@reverse')
|
140
|
-
|
148
|
+
al = context.compact_iri('@reverse', vocab: true)
|
149
|
+
log_debug("", depth: log_depth.to_i) {"remainder: #{al} => #{compacted_value.inspect}"}
|
141
150
|
result[al] = compacted_value
|
142
151
|
end
|
143
152
|
next
|
@@ -146,8 +155,9 @@ module JSON::LD
|
|
146
155
|
if expanded_property == '@preserve'
|
147
156
|
# Compact using `property`
|
148
157
|
compacted_value = compact(expanded_value, base: base,
|
149
|
-
property: property
|
150
|
-
|
158
|
+
property: property,
|
159
|
+
log_depth: log_depth.to_i + 1)
|
160
|
+
log_debug("@preserve", depth: log_depth.to_i) {"compacted_value: #{compacted_value.inspect}"}
|
151
161
|
|
152
162
|
unless compacted_value.is_a?(Array) && compacted_value.empty?
|
153
163
|
result['@preserve'] = compacted_value
|
@@ -156,14 +166,14 @@ module JSON::LD
|
|
156
166
|
end
|
157
167
|
|
158
168
|
if expanded_property == '@index' && context.container(property).include?('@index')
|
159
|
-
|
169
|
+
log_debug("@index", depth: log_depth.to_i) {"drop @index"}
|
160
170
|
next
|
161
171
|
end
|
162
172
|
|
163
173
|
# Otherwise, if expanded property is @direction, @index, @value, or @language:
|
164
174
|
if EXPANDED_PROPERTY_DIRECTION_INDEX_LANGUAGE_VALUE.include?(expanded_property)
|
165
175
|
al = context.compact_iri(expanded_property, vocab: true)
|
166
|
-
|
176
|
+
log_debug(expanded_property, depth: log_depth.to_i) {"#{al} => #{expanded_value.inspect}"}
|
167
177
|
result[al] = expanded_value
|
168
178
|
next
|
169
179
|
end
|
@@ -211,8 +221,9 @@ module JSON::LD
|
|
211
221
|
end
|
212
222
|
|
213
223
|
compacted_item = compact(value, base: base,
|
214
|
-
property: item_active_property
|
215
|
-
|
224
|
+
property: item_active_property,
|
225
|
+
log_depth: log_depth.to_i + 1)
|
226
|
+
log_debug("", depth: log_depth.to_i) {" => compacted key: #{item_active_property.inspect} for #{compacted_item.inspect}"}
|
216
227
|
|
217
228
|
# handle @list
|
218
229
|
if list?(expanded_item)
|
@@ -220,7 +231,7 @@ module JSON::LD
|
|
220
231
|
unless container.include?('@list')
|
221
232
|
al = context.compact_iri('@list', vocab: true)
|
222
233
|
compacted_item = {al => compacted_item}
|
223
|
-
if expanded_item.
|
234
|
+
if expanded_item.key?('@index')
|
224
235
|
key = context.compact_iri('@index', vocab: true)
|
225
236
|
compacted_item[key] = expanded_item['@index']
|
226
237
|
end
|
@@ -265,7 +276,7 @@ module JSON::LD
|
|
265
276
|
al = context.compact_iri('@id', vocab: true)
|
266
277
|
compacted_item[al] = context.compact_iri(expanded_item['@id'], vocab: false)
|
267
278
|
end
|
268
|
-
if expanded_item.
|
279
|
+
if expanded_item.key?('@index')
|
269
280
|
key = context.compact_iri('@index', vocab: true)
|
270
281
|
compacted_item[key] = expanded_item['@index']
|
271
282
|
end
|
@@ -315,7 +326,8 @@ module JSON::LD
|
|
315
326
|
if compacted_item.keys.length == 1 && expanded_item.keys.include?('@id')
|
316
327
|
compacted_item = compact({'@id' => expanded_item['@id']},
|
317
328
|
base: base,
|
318
|
-
property: item_active_property
|
329
|
+
property: item_active_property,
|
330
|
+
log_depth: log_depth.to_i + 1)
|
319
331
|
end
|
320
332
|
compacted_item
|
321
333
|
end
|
@@ -332,7 +344,7 @@ module JSON::LD
|
|
332
344
|
result
|
333
345
|
else
|
334
346
|
# For other types, the compacted value is the element value
|
335
|
-
|
347
|
+
log_debug("compact", depth: log_depth.to_i) {element.class.to_s}
|
336
348
|
element
|
337
349
|
end
|
338
350
|
|
data/lib/json/ld/conneg.rb
CHANGED
@@ -46,7 +46,7 @@ module JSON::LD
|
|
46
46
|
#
|
47
47
|
# @param [Hash{String => String}] env
|
48
48
|
# @return [Array(Integer, Hash, #each)] Status, Headers and Body
|
49
|
-
# @see
|
49
|
+
# @see https://rubydoc.info/github/rack/rack/file/SPEC
|
50
50
|
def call(env)
|
51
51
|
response = app.call(env)
|
52
52
|
body = response[2].respond_to?(:body) ? response[2].body : response[2]
|
data/lib/json/ld/context.rb
CHANGED
@@ -104,16 +104,12 @@ module JSON::LD
|
|
104
104
|
# @see #initialize
|
105
105
|
# @see #parse
|
106
106
|
# @param [String, #read, Array, Hash, Context] local_context
|
107
|
-
# @param [String, #to_s]
|
107
|
+
# @param [String, #to_s] base (nil)
|
108
108
|
# The Base IRI to use when expanding the document. This overrides the value of `input` if it is a _IRI_. If not specified and `input` is not an _IRI_, the base IRI defaults to the current document IRI if in a browser context, or the empty string if there is no document context.
|
109
|
-
# @param [Proc] :documentLoader (nil)
|
110
|
-
# The callback of the loader to be used to retrieve remote documents and contexts. If specified, it must be used to retrieve remote documents and contexts; otherwise, if not specified, the processor's built-in loader must be used. See {API.documentLoader} for the method signature.
|
111
109
|
# @param [Boolean] override_protected (false)
|
112
110
|
# Protected terms may be cleared.
|
113
111
|
# @param [Boolean] propagate (true)
|
114
112
|
# If false, retains any previously defined term, which can be rolled back when the descending into a new node object changes.
|
115
|
-
# @param [Boolean] validate (false)
|
116
|
-
# Extra validatation
|
117
113
|
# @raise [JsonLdError]
|
118
114
|
# on a remote context load error, syntax error, or a reference to a term which is not defined.
|
119
115
|
# @return [Context]
|
@@ -231,14 +227,12 @@ module JSON::LD
|
|
231
227
|
#
|
232
228
|
#
|
233
229
|
# @param [String, #read, Array, Hash, Context] local_context
|
234
|
-
# @param [String, #to_s]
|
230
|
+
# @param [String, #to_s] base
|
235
231
|
# The Base IRI to use when expanding the document. This overrides the value of `input` if it is a _IRI_. If not specified and `input` is not an _IRI_, the base IRI defaults to the current document IRI if in a browser context, or the empty string if there is no document context.
|
236
232
|
# @param [Boolean] override_protected Protected terms may be cleared.
|
237
233
|
# @param [Boolean] propagate (true)
|
238
234
|
# If false, retains any previously defined term, which can be rolled back when the descending into a new node object changes.
|
239
235
|
# @param [Array<String>] remote_contexts ([])
|
240
|
-
# @param [Boolean] validate (false)
|
241
|
-
# Extra validatation
|
242
236
|
# @param [Boolean] validate_scoped (true).
|
243
237
|
# Validate scoped context, loading if necessary.
|
244
238
|
# If false, do not load scoped contexts.
|
@@ -320,7 +314,7 @@ module JSON::LD
|
|
320
314
|
#context_opts.delete(:headers)
|
321
315
|
JSON::LD::API.loadRemoteDocument(context.to_s, **context_opts) do |remote_doc|
|
322
316
|
# 3.2.5) Dereference context. If the dereferenced document has no top-level JSON object with an @context member, an invalid remote context has been detected and processing is aborted; otherwise, set context to the value of that member.
|
323
|
-
raise JsonLdError::InvalidRemoteContext, "#{context}" unless remote_doc.document.is_a?(Hash) && remote_doc.document.
|
317
|
+
raise JsonLdError::InvalidRemoteContext, "#{context}" unless remote_doc.document.is_a?(Hash) && remote_doc.document.key?('@context')
|
324
318
|
|
325
319
|
# Parse stand-alone
|
326
320
|
ctx = Context.new(unfrozen: true, **options).dup
|
@@ -358,7 +352,7 @@ module JSON::LD
|
|
358
352
|
'@propagate' => :propagate=,
|
359
353
|
'@vocab' => :vocab=,
|
360
354
|
}.each do |key, setter|
|
361
|
-
next unless context.
|
355
|
+
next unless context.key?(key)
|
362
356
|
if key == '@import'
|
363
357
|
# Retrieve remote context and merge the remaining context object into the result.
|
364
358
|
raise JsonLdError::InvalidContextEntry, "@import may only be used in 1.1 mode}" if result.processingMode("json-ld-1.0")
|
@@ -373,11 +367,11 @@ module JSON::LD
|
|
373
367
|
# FIXME: should cache this, but ContextCache is for parsed contexts
|
374
368
|
JSON::LD::API.loadRemoteDocument(import_loc, **context_opts) do |remote_doc|
|
375
369
|
# Dereference import_loc. If the dereferenced document has no top-level JSON object with an @context member, an invalid remote context has been detected and processing is aborted; otherwise, set context to the value of that member.
|
376
|
-
raise JsonLdError::InvalidRemoteContext, "#{import_loc}" unless remote_doc.document.is_a?(Hash) && remote_doc.document.
|
370
|
+
raise JsonLdError::InvalidRemoteContext, "#{import_loc}" unless remote_doc.document.is_a?(Hash) && remote_doc.document.key?('@context')
|
377
371
|
import_context = remote_doc.document['@context']
|
378
372
|
import_context.delete('@base')
|
379
373
|
raise JsonLdError::InvalidRemoteContext, "#{import_context.to_json} must be an object" unless import_context.is_a?(Hash)
|
380
|
-
raise JsonLdError::InvalidContextEntry, "#{import_context.to_json} must not include @import entry" if import_context.
|
374
|
+
raise JsonLdError::InvalidContextEntry, "#{import_context.to_json} must not include @import entry" if import_context.key?('@import')
|
381
375
|
context.delete(key)
|
382
376
|
context = import_context.merge(context)
|
383
377
|
end
|
@@ -419,9 +413,7 @@ module JSON::LD
|
|
419
413
|
# Merge in a context, creating a new context with updates from `context`
|
420
414
|
#
|
421
415
|
# @param [Context] context
|
422
|
-
# @param [Boolean] protected mark resulting context as protected
|
423
416
|
# @param [Boolean] override_protected Allow or disallow protected terms to be changed
|
424
|
-
# @param [Boolean]
|
425
417
|
# @return [Context]
|
426
418
|
def merge(context, override_protected: false)
|
427
419
|
ctx = Context.new(term_definitions: self.term_definitions, standard_prefixes: options[:standard_prefixes])
|
@@ -469,8 +461,6 @@ module JSON::LD
|
|
469
461
|
# @param [String, RDF::URI] base for resolving document-relative IRIs
|
470
462
|
# @param [Boolean] protected if true, causes all terms to be marked protected
|
471
463
|
# @param [Boolean] override_protected Protected terms may be cleared.
|
472
|
-
# @param [Boolean] propagate
|
473
|
-
# Context is propagated across node objects.
|
474
464
|
# @param [Array<String>] remote_contexts
|
475
465
|
# @param [Boolean] validate_scoped (true).
|
476
466
|
# Validate scoped context, loading if necessary.
|
@@ -552,7 +542,7 @@ module JSON::LD
|
|
552
542
|
# Potentially note that the term is protected
|
553
543
|
definition.protected = value.fetch('@protected', protected)
|
554
544
|
|
555
|
-
if value.
|
545
|
+
if value.key?('@type')
|
556
546
|
type = value['@type']
|
557
547
|
# SPEC FIXME: @type may be nil
|
558
548
|
type = case type
|
@@ -576,7 +566,7 @@ module JSON::LD
|
|
576
566
|
definition.type_mapping = type
|
577
567
|
end
|
578
568
|
|
579
|
-
if value.
|
569
|
+
if value.key?('@reverse')
|
580
570
|
raise JsonLdError::InvalidReverseProperty, "unexpected key in #{value.inspect} on term #{term.inspect}" if
|
581
571
|
value.key?('@id') || value.key?('@nest')
|
582
572
|
raise JsonLdError::InvalidIRIMapping, "expected value of @reverse to be a string: #{value['@reverse'].inspect} on term #{term.inspect}" unless
|
@@ -602,7 +592,7 @@ module JSON::LD
|
|
602
592
|
warn "[DEPRECATION] Blank Node terms deprecated in JSON-LD 1.1." if @options[:validate] && processingMode('json-ld-1.1') && definition.id.to_s.start_with?("_:")
|
603
593
|
|
604
594
|
# If value contains an @container member, set the container mapping of definition to its value; if its value is neither @set, @index, @type, @id, an absolute IRI nor null, an invalid reverse property error has been detected (reverse properties only support set- and index-containers) and processing is aborted.
|
605
|
-
if value.
|
595
|
+
if value.key?('@container')
|
606
596
|
container = value['@container']
|
607
597
|
raise JsonLdError::InvalidReverseProperty,
|
608
598
|
"unknown mapping for '@container' to #{container.inspect} on term #{term.inspect}" unless
|
@@ -610,9 +600,9 @@ module JSON::LD
|
|
610
600
|
definition.container_mapping = check_container(container, local_context, defined, term)
|
611
601
|
end
|
612
602
|
definition.reverse_property = true
|
613
|
-
elsif value.
|
603
|
+
elsif value.key?('@id') && value['@id'].nil?
|
614
604
|
# Allowed to reserve a null term, which may be protected
|
615
|
-
elsif value.
|
605
|
+
elsif value.key?('@id') && value['@id'] != term
|
616
606
|
raise JsonLdError::InvalidIRIMapping, "expected value of @id to be a string: #{value['@id'].inspect} on term #{term.inspect}" unless
|
617
607
|
value['@id'].is_a?(String)
|
618
608
|
|
@@ -647,7 +637,7 @@ module JSON::LD
|
|
647
637
|
elsif term[1..-1].include?(':')
|
648
638
|
# If term is a compact IRI with a prefix that is a key in local context then a dependency has been found. Use this algorithm recursively passing active context, local context, the prefix as term, and defined.
|
649
639
|
prefix, suffix = term.split(':', 2)
|
650
|
-
create_term_definition(local_context, prefix, defined, protected: protected) if local_context.
|
640
|
+
create_term_definition(local_context, prefix, defined, protected: protected) if local_context.key?(prefix)
|
651
641
|
|
652
642
|
definition.id = if td = term_definitions[prefix]
|
653
643
|
# If term's prefix has a term definition in active context, set the IRI mapping for definition to the result of concatenating the value associated with the prefix's IRI mapping and the term's suffix.
|
@@ -674,7 +664,7 @@ module JSON::LD
|
|
674
664
|
|
675
665
|
@iri_to_term[definition.id] = term if simple_term && definition.id
|
676
666
|
|
677
|
-
if value.
|
667
|
+
if value.key?('@container')
|
678
668
|
#log_debug("") {"container_mapping: #{value['@container'].inspect}"}
|
679
669
|
definition.container_mapping = check_container(value['@container'], local_context, defined, term)
|
680
670
|
|
@@ -689,14 +679,14 @@ module JSON::LD
|
|
689
679
|
end
|
690
680
|
end
|
691
681
|
|
692
|
-
if value.
|
682
|
+
if value.key?('@index')
|
693
683
|
# property-based indexing
|
694
684
|
raise JsonLdError::InvalidTermDefinition, "@index without @index in @container: #{value['@index']} on term #{term.inspect}" unless definition.container_mapping.include?('@index')
|
695
685
|
raise JsonLdError::InvalidTermDefinition, "@index must expand to an IRI: #{value['@index']} on term #{term.inspect}" unless value['@index'].is_a?(String) && !value['@index'].start_with?('@')
|
696
686
|
definition.index = value['@index'].to_s
|
697
687
|
end
|
698
688
|
|
699
|
-
if value.
|
689
|
+
if value.key?('@context')
|
700
690
|
begin
|
701
691
|
new_ctx = self.parse(value['@context'],
|
702
692
|
base: base,
|
@@ -714,7 +704,7 @@ module JSON::LD
|
|
714
704
|
end
|
715
705
|
end
|
716
706
|
|
717
|
-
if value.
|
707
|
+
if value.key?('@language')
|
718
708
|
language = value['@language']
|
719
709
|
language = case value['@language']
|
720
710
|
when String
|
@@ -732,14 +722,14 @@ module JSON::LD
|
|
732
722
|
definition.language_mapping = language || false
|
733
723
|
end
|
734
724
|
|
735
|
-
if value.
|
725
|
+
if value.key?('@direction')
|
736
726
|
direction = value['@direction']
|
737
727
|
raise JsonLdError::InvalidBaseDirection, "direction must be null, 'ltr', or 'rtl', was #{language.inspect}} on term #{term.inspect}" unless direction.nil? || %w(ltr rtl).include?(direction)
|
738
728
|
#log_debug("") {"direction_mapping: #{direction.inspect}"}
|
739
729
|
definition.direction_mapping = direction || false
|
740
730
|
end
|
741
731
|
|
742
|
-
if value.
|
732
|
+
if value.key?('@nest')
|
743
733
|
nest = value['@nest']
|
744
734
|
raise JsonLdError::InvalidNestValue, "nest must be a string, was #{nest.inspect}} on term #{term.inspect}" unless nest.is_a?(String)
|
745
735
|
raise JsonLdError::InvalidNestValue, "nest must not be a keyword other than @nest, was #{nest.inspect}} on term #{term.inspect}" if nest.match?(/^@[a-zA-Z]+$/) && nest != '@nest'
|
@@ -747,7 +737,7 @@ module JSON::LD
|
|
747
737
|
definition.nest = nest
|
748
738
|
end
|
749
739
|
|
750
|
-
if value.
|
740
|
+
if value.key?('@prefix')
|
751
741
|
raise JsonLdError::InvalidTermDefinition, "@prefix used on compact or relative IRI term #{term.inspect}" if term.match?(%r{:|/})
|
752
742
|
case pfx = value['@prefix']
|
753
743
|
when TrueClass, FalseClass
|
@@ -846,7 +836,7 @@ module JSON::LD
|
|
846
836
|
# If contex has a @version member, it's value MUST be 1.1, otherwise an "invalid @version value" has been detected, and processing is aborted.
|
847
837
|
# If processingMode has been set, and it is not "json-ld-1.1", a "processing mode conflict" has been detecting, and processing is aborted.
|
848
838
|
#
|
849
|
-
# @param [String, Number]
|
839
|
+
# @param [String, Number] value
|
850
840
|
# @return [String]
|
851
841
|
# @raise [JsonLdError::ProcessingModeConflict]
|
852
842
|
def processingMode=(value = nil, **options)
|
@@ -1028,7 +1018,7 @@ module JSON::LD
|
|
1028
1018
|
|
1029
1019
|
term_sym = term.empty? ? "" : term.to_sym
|
1030
1020
|
iri_to_term.delete(term_definitions[term].id.to_s) if term_definitions[term].id.is_a?(String)
|
1031
|
-
@options[:prefixes][term_sym] = value if @options.
|
1021
|
+
@options[:prefixes][term_sym] = value if @options.key?(:prefixes)
|
1032
1022
|
iri_to_term[value.to_s] = term
|
1033
1023
|
term_definitions[term]
|
1034
1024
|
end
|
@@ -1048,7 +1038,7 @@ module JSON::LD
|
|
1048
1038
|
# @param [Term, #to_s] term in unexpanded form
|
1049
1039
|
# @return [Array<'@index', '@language', '@index', '@set', '@type', '@id', '@graph'>]
|
1050
1040
|
def container(term)
|
1051
|
-
return [term] if term == '@list'
|
1041
|
+
return Set[term] if term == '@list'
|
1052
1042
|
term = find_definition(term)
|
1053
1043
|
term ? term.container_mapping : Set.new
|
1054
1044
|
end
|
@@ -1144,7 +1134,7 @@ module JSON::LD
|
|
1144
1134
|
# @return [Term] related term definition
|
1145
1135
|
def reverse_term(term)
|
1146
1136
|
# Direct lookup of term
|
1147
|
-
term = term_definitions[term.to_s] if term_definitions.
|
1137
|
+
term = term_definitions[term.to_s] if term_definitions.key?(term.to_s) && !term.is_a?(TermDefinition)
|
1148
1138
|
|
1149
1139
|
# Lookup term, assuming term is an IRI
|
1150
1140
|
unless term.is_a?(TermDefinition)
|
@@ -1192,7 +1182,7 @@ module JSON::LD
|
|
1192
1182
|
defined = defined || {} # if we initialized in the keyword arg we would allocate {} at each invokation, even in the 2 (common) early returns above.
|
1193
1183
|
|
1194
1184
|
# If local context is not null, it contains a key that equals value, and the value associated with the key that equals value in defined is not true, then invoke the Create Term Definition subalgorithm, passing active context, local context, value as term, and defined. This will ensure that a term definition is created for value in active context during Context Processing.
|
1195
|
-
if local_context && local_context.
|
1185
|
+
if local_context && local_context.key?(value) && !defined[value]
|
1196
1186
|
create_term_definition(local_context, value, defined)
|
1197
1187
|
end
|
1198
1188
|
|
@@ -1222,7 +1212,7 @@ module JSON::LD
|
|
1222
1212
|
end
|
1223
1213
|
|
1224
1214
|
# If local context is not null, it contains a key that equals prefix, and the value associated with the key that equals prefix in defined is not true, invoke the Create Term Definition algorithm, passing active context, local context, prefix as term, and defined. This will ensure that a term definition is created for prefix in active context during Context Processing.
|
1225
|
-
if local_context && local_context.
|
1215
|
+
if local_context && local_context.key?(prefix) && !defined[prefix]
|
1226
1216
|
create_term_definition(local_context, prefix, defined)
|
1227
1217
|
end
|
1228
1218
|
|
@@ -1297,7 +1287,7 @@ module JSON::LD
|
|
1297
1287
|
return if iri.nil?
|
1298
1288
|
iri = iri.to_s
|
1299
1289
|
|
1300
|
-
if vocab && inverse_context.
|
1290
|
+
if vocab && inverse_context.key?(iri)
|
1301
1291
|
default_language = if self.default_direction
|
1302
1292
|
"#{self.default_language}_#{self.default_direction}".downcase
|
1303
1293
|
else
|
@@ -1308,7 +1298,7 @@ module JSON::LD
|
|
1308
1298
|
containers.concat(CONTAINERS_INDEX_SET) if index?(value) && !graph?(value)
|
1309
1299
|
|
1310
1300
|
# If the value is a JSON Object with the key @preserve, use the value of @preserve.
|
1311
|
-
value = value['@preserve'].first if value.is_a?(Hash) && value.
|
1301
|
+
value = value['@preserve'].first if value.is_a?(Hash) && value.key?('@preserve')
|
1312
1302
|
|
1313
1303
|
if reverse
|
1314
1304
|
tl, tl_value = "@type", "@reverse"
|
@@ -1322,11 +1312,11 @@ module JSON::LD
|
|
1322
1312
|
list.each do |item|
|
1323
1313
|
item_language, item_type = "@none", "@none"
|
1324
1314
|
if value?(item)
|
1325
|
-
if item.
|
1315
|
+
if item.key?('@direction')
|
1326
1316
|
item_language = "#{item['@language']}_#{item['@direction']}".downcase
|
1327
|
-
elsif item.
|
1317
|
+
elsif item.key?('@language')
|
1328
1318
|
item_language = item['@language'].downcase
|
1329
|
-
elsif item.
|
1319
|
+
elsif item.key?('@type')
|
1330
1320
|
item_type = item['@type']
|
1331
1321
|
else
|
1332
1322
|
item_language = "@null"
|
@@ -1354,14 +1344,14 @@ module JSON::LD
|
|
1354
1344
|
elsif graph?(value)
|
1355
1345
|
# Prefer @index and @id containers, then @graph, then @index
|
1356
1346
|
containers.concat(CONTAINERS_GRAPH_INDEX_INDEX) if index?(value)
|
1357
|
-
containers.concat(CONTAINERS_GRAPH) if value.
|
1347
|
+
containers.concat(CONTAINERS_GRAPH) if value.key?('@id')
|
1358
1348
|
|
1359
1349
|
# Prefer an @graph container next
|
1360
1350
|
containers.concat(CONTAINERS_GRAPH_SET)
|
1361
1351
|
|
1362
1352
|
# Lastly, in 1.1, any graph can be indexed on @index or @id, so add if we haven't already
|
1363
1353
|
containers.concat(CONTAINERS_GRAPH_INDEX) unless index?(value)
|
1364
|
-
containers.concat(CONTAINERS_GRAPH) unless value.
|
1354
|
+
containers.concat(CONTAINERS_GRAPH) unless value.key?('@id')
|
1365
1355
|
containers.concat(CONTAINERS_INDEX_SET) unless index?(value)
|
1366
1356
|
containers << '@set'
|
1367
1357
|
|
@@ -1369,13 +1359,13 @@ module JSON::LD
|
|
1369
1359
|
else
|
1370
1360
|
if value?(value)
|
1371
1361
|
# In 1.1, an language map can be used to index values using @none
|
1372
|
-
if value.
|
1362
|
+
if value.key?('@language') && !index?(value)
|
1373
1363
|
tl_value = value['@language'].downcase
|
1374
1364
|
tl_value += "_#{value['@direction']}" if value['@direction']
|
1375
1365
|
containers.concat(CONTAINERS_LANGUAGE)
|
1376
|
-
elsif value.
|
1366
|
+
elsif value.key?('@direction') && !index?(value)
|
1377
1367
|
tl_value = "_#{value['@direction']}"
|
1378
|
-
elsif value.
|
1368
|
+
elsif value.key?('@type')
|
1379
1369
|
tl_value = value['@type']
|
1380
1370
|
tl = '@type'
|
1381
1371
|
end
|
@@ -1397,7 +1387,7 @@ module JSON::LD
|
|
1397
1387
|
tl_value ||= '@null'
|
1398
1388
|
preferred_values = []
|
1399
1389
|
preferred_values << '@reverse' if tl_value == '@reverse'
|
1400
|
-
if (tl_value == '@id' || tl_value == '@reverse') && value.is_a?(Hash) && value.
|
1390
|
+
if (tl_value == '@id' || tl_value == '@reverse') && value.is_a?(Hash) && value.key?('@id')
|
1401
1391
|
t_iri = compact_iri(value['@id'], vocab: true, base: base)
|
1402
1392
|
if (r_td = term_definitions[t_iri]) && r_td.id == value['@id']
|
1403
1393
|
preferred_values.concat(CONTAINERS_VOCAB_ID)
|
@@ -1423,7 +1413,7 @@ module JSON::LD
|
|
1423
1413
|
# At this point, there is no simple term that iri can be compacted to. If vocab is true and active context has a vocabulary mapping:
|
1424
1414
|
if vocab && self.vocab && iri.start_with?(self.vocab) && iri.length > self.vocab.length
|
1425
1415
|
suffix = iri[self.vocab.length..-1]
|
1426
|
-
return suffix unless term_definitions.
|
1416
|
+
return suffix unless term_definitions.key?(suffix)
|
1427
1417
|
end
|
1428
1418
|
|
1429
1419
|
# The iri could not be compacted using the active context's vocabulary mapping. Try to create a compact IRI, starting by initializing compact IRI to null. This variable will be used to tore the created compact IRI, if any.
|
@@ -1437,7 +1427,7 @@ module JSON::LD
|
|
1437
1427
|
|
1438
1428
|
suffix = iri[td.id.length..-1]
|
1439
1429
|
ciri = "#{term}:#{suffix}"
|
1440
|
-
candidates << ciri unless value && term_definitions.
|
1430
|
+
candidates << ciri unless value && term_definitions.key?(ciri)
|
1441
1431
|
end
|
1442
1432
|
|
1443
1433
|
return candidates.sort.first if !candidates.empty?
|
@@ -1465,6 +1455,8 @@ module JSON::LD
|
|
1465
1455
|
if !vocab
|
1466
1456
|
# transform iri to a relative IRI using the document's base IRI
|
1467
1457
|
iri = remove_base(self.base || base, iri)
|
1458
|
+
# Make . relative if it has the form of a keyword.
|
1459
|
+
iri = "./#{iri}" if iri.match?(/^@[a-zA-Z]+$/)
|
1468
1460
|
return iri
|
1469
1461
|
else
|
1470
1462
|
return iri
|
@@ -1533,16 +1525,16 @@ module JSON::LD
|
|
1533
1525
|
res['@language'] = lang
|
1534
1526
|
end
|
1535
1527
|
res['@direction'] = dir
|
1536
|
-
elsif useNativeTypes && RDF_LITERAL_NATIVE_TYPES.include?(value.datatype)
|
1528
|
+
elsif useNativeTypes && RDF_LITERAL_NATIVE_TYPES.include?(value.datatype) && value.valid?
|
1537
1529
|
res['@type'] = uri(coerce(property)) if coerce(property)
|
1538
1530
|
res['@value'] = value.object
|
1539
1531
|
else
|
1540
|
-
value.canonicalize! if value.datatype == RDF::XSD.double
|
1532
|
+
value.canonicalize! if value.valid? && value.datatype == RDF::XSD.double
|
1541
1533
|
if coerce(property)
|
1542
1534
|
res['@type'] = uri(coerce(property)).to_s
|
1543
|
-
elsif value.
|
1535
|
+
elsif value.datatype?
|
1544
1536
|
res['@type'] = uri(value.datatype).to_s
|
1545
|
-
elsif value.
|
1537
|
+
elsif value.language? || language(property)
|
1546
1538
|
res['@language'] = (value.language || language(property)).to_s
|
1547
1539
|
end
|
1548
1540
|
res['@value'] = value.to_s
|
@@ -1590,15 +1582,15 @@ module JSON::LD
|
|
1590
1582
|
direction = direction(property)
|
1591
1583
|
|
1592
1584
|
result = case
|
1593
|
-
when coerce(property) == '@id' && value.
|
1585
|
+
when coerce(property) == '@id' && value.key?('@id') && (value.keys - %w(@id @index)).empty?
|
1594
1586
|
# Compact an @id coercion
|
1595
1587
|
#log_debug("") {" (@id & coerce)"}
|
1596
1588
|
compact_iri(value['@id'], base: base)
|
1597
|
-
when coerce(property) == '@vocab' && value.
|
1589
|
+
when coerce(property) == '@vocab' && value.key?('@id') && (value.keys - %w(@id @index)).empty?
|
1598
1590
|
# Compact an @id coercion
|
1599
1591
|
#log_debug("") {" (@id & coerce & vocab)"}
|
1600
1592
|
compact_iri(value['@id'], vocab: true)
|
1601
|
-
when value.
|
1593
|
+
when value.key?('@id')
|
1602
1594
|
#log_debug("") {" (@id)"}
|
1603
1595
|
# return value as is
|
1604
1596
|
value
|
@@ -1619,7 +1611,7 @@ module JSON::LD
|
|
1619
1611
|
value
|
1620
1612
|
end
|
1621
1613
|
|
1622
|
-
if result.is_a?(Hash) && result.
|
1614
|
+
if result.is_a?(Hash) && result.key?('@type') && value['@type'] != '@json'
|
1623
1615
|
# Compact values of @type
|
1624
1616
|
c_type = if result['@type'].is_a?(Array)
|
1625
1617
|
result['@type'].map {|t| compact_iri(t, vocab: true)}
|
@@ -1867,11 +1859,11 @@ module JSON::LD
|
|
1867
1859
|
container_map = inverse_context[iri]
|
1868
1860
|
#log_debug(" ") {"container_map: #{container_map.inspect}"}
|
1869
1861
|
containers.each do |container|
|
1870
|
-
next unless container_map.
|
1862
|
+
next unless container_map.key?(container)
|
1871
1863
|
tl_map = container_map[container]
|
1872
1864
|
value_map = tl_map[type_language]
|
1873
1865
|
preferred_values.each do |item|
|
1874
|
-
next unless value_map.
|
1866
|
+
next unless value_map.key?(item)
|
1875
1867
|
#log_debug("=>") {value_map[item].inspect}
|
1876
1868
|
return value_map[item]
|
1877
1869
|
end
|
@@ -2064,7 +2056,7 @@ module JSON::LD
|
|
2064
2056
|
# @param ["ltr", "rtl"] direction_mapping
|
2065
2057
|
# Direction mapping of term, `false` is used if there is an explicit direction mapping for this term
|
2066
2058
|
# @param [Boolean] reverse_property
|
2067
|
-
# @param [Boolean] protected
|
2059
|
+
# @param [Boolean] protected mark resulting context as protected
|
2068
2060
|
# @param [String] nest term used for nest properties
|
2069
2061
|
# @param [Boolean] simple
|
2070
2062
|
# This is a simple term definition, not an expanded term definition
|