json-ld 3.1.1 → 3.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +124 -48
- data/VERSION +1 -1
- data/bin/jsonld +27 -30
- data/lib/json/ld.rb +12 -7
- data/lib/json/ld/api.rb +41 -31
- data/lib/json/ld/compact.rb +58 -37
- data/lib/json/ld/conneg.rb +1 -1
- data/lib/json/ld/context.rb +641 -540
- data/lib/json/ld/expand.rb +160 -77
- data/lib/json/ld/flatten.rb +1 -1
- data/lib/json/ld/format.rb +20 -7
- data/lib/json/ld/frame.rb +0 -1
- data/lib/json/ld/from_rdf.rb +40 -17
- data/lib/json/ld/html/nokogiri.rb +2 -1
- data/lib/json/ld/html/rexml.rb +2 -1
- data/lib/json/ld/reader.rb +20 -11
- data/lib/json/ld/streaming_reader.rb +578 -0
- data/lib/json/ld/to_rdf.rb +9 -5
- data/lib/json/ld/writer.rb +10 -3
- data/spec/compact_spec.rb +1 -0
- data/spec/context_spec.rb +20 -73
- data/spec/expand_spec.rb +277 -9
- data/spec/frame_spec.rb +44 -0
- data/spec/from_rdf_spec.rb +181 -0
- data/spec/matchers.rb +1 -1
- data/spec/reader_spec.rb +33 -34
- data/spec/streaming_reader_spec.rb +237 -0
- data/spec/suite_expand_spec.rb +2 -2
- data/spec/suite_frame_spec.rb +0 -1
- data/spec/suite_helper.rb +18 -8
- data/spec/suite_to_rdf_spec.rb +2 -1
- data/spec/to_rdf_spec.rb +206 -0
- metadata +65 -62
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/)
|
@@ -34,6 +34,8 @@ module JSON
|
|
34
34
|
autoload :Normalize, 'json/ld/normalize'
|
35
35
|
autoload :Reader, 'json/ld/reader'
|
36
36
|
autoload :Resource, 'json/ld/resource'
|
37
|
+
autoload :StreamingReader, 'json/ld/streaming_reader'
|
38
|
+
autoload :StreamingWriter, 'json/ld/streaming_writer'
|
37
39
|
autoload :VERSION, 'json/ld/version'
|
38
40
|
autoload :Writer, 'json/ld/writer'
|
39
41
|
|
@@ -52,13 +54,13 @@ module JSON
|
|
52
54
|
@direction
|
53
55
|
@embed
|
54
56
|
@explicit
|
55
|
-
@json
|
56
|
-
@id
|
57
|
-
@included
|
58
|
-
@index
|
59
57
|
@first
|
60
58
|
@graph
|
59
|
+
@id
|
61
60
|
@import
|
61
|
+
@included
|
62
|
+
@index
|
63
|
+
@json
|
62
64
|
@language
|
63
65
|
@list
|
64
66
|
@nest
|
@@ -66,6 +68,7 @@ module JSON
|
|
66
68
|
@omitDefault
|
67
69
|
@propagate
|
68
70
|
@protected
|
71
|
+
@preserve
|
69
72
|
@requireAll
|
70
73
|
@reverse
|
71
74
|
@set
|
@@ -134,6 +137,7 @@ module JSON
|
|
134
137
|
class InvalidNestValue < JsonLdError; @code = "invalid @nest value"; end
|
135
138
|
class InvalidPrefixValue < JsonLdError; @code = "invalid @prefix value"; end
|
136
139
|
class InvalidPropagateValue < JsonLdError; @code = "invalid @propagate value"; end
|
140
|
+
class InvalidEmbeddedNode < JsonLdError; @code = "invalid reified node"; end
|
137
141
|
class InvalidRemoteContext < JsonLdError; @code = "invalid remote context"; end
|
138
142
|
class InvalidReverseProperty < JsonLdError; @code = "invalid reverse property"; end
|
139
143
|
class InvalidReversePropertyMap < JsonLdError; @code = "invalid reverse property map"; end
|
@@ -142,6 +146,7 @@ module JSON
|
|
142
146
|
class InvalidScopedContext < JsonLdError; @code = "invalid scoped context"; end
|
143
147
|
class InvalidScriptElement < JsonLdError; @code = "invalid script element"; end
|
144
148
|
class InvalidSetOrListObject < JsonLdError; @code = "invalid set or list object"; end
|
149
|
+
class InvalidStreamingKeyOrder < JsonLdError; @code = 'invalid streaming key order' end
|
145
150
|
class InvalidTermDefinition < JsonLdError; @code = "invalid term definition"; end
|
146
151
|
class InvalidBaseDirection < JsonLdError; @code = "invalid base direction"; end
|
147
152
|
class InvalidTypedValue < JsonLdError; @code = "invalid typed value"; end
|
@@ -154,7 +159,7 @@ module JSON
|
|
154
159
|
class KeywordRedefinition < JsonLdError; @code = "keyword redefinition"; end
|
155
160
|
class LoadingDocumentFailed < JsonLdError; @code = "loading document failed"; end
|
156
161
|
class LoadingRemoteContextFailed < JsonLdError; @code = "loading remote context failed"; end
|
157
|
-
class ContextOverflow < JsonLdError; @code = "
|
162
|
+
class ContextOverflow < JsonLdError; @code = "context overflow"; end
|
158
163
|
class MissingIncludedReferent < JsonLdError; @code = "missing @included referent"; end
|
159
164
|
class MultipleContextLinkHeaders < JsonLdError; @code = "multiple context link headers"; end
|
160
165
|
class ProtectedTermRedefinition < JsonLdError; @code = "protected term redefinition"; end
|
data/lib/json/ld/api.rb
CHANGED
@@ -66,7 +66,7 @@ module JSON::LD
|
|
66
66
|
# @param [String, #read, Hash, Array, JSON::LD::Context] context
|
67
67
|
# An external context to use additionally to the context embedded in input when expanding the input.
|
68
68
|
# @param [Hash{Symbol => Object}] options
|
69
|
-
# @option options [String, #to_s] :base
|
69
|
+
# @option options [RDF::URI, String, #to_s] :base
|
70
70
|
# 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. If not specified, and a base IRI is found from `input`, options[:base] will be modified with this value.
|
71
71
|
# @option options [Boolean] :compactArrays (true)
|
72
72
|
# If set to `true`, the JSON-LD processor replaces arrays with just one element with that element during compaction. If set to `false`, all arrays will remain arrays even if they have just one element.
|
@@ -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* 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)
|
@@ -108,6 +110,7 @@ module JSON::LD
|
|
108
110
|
}.merge(options)
|
109
111
|
@namer = unique_bnodes ? BlankNodeUniqer.new : (rename_bnodes ? BlankNodeNamer.new("b") : BlankNodeMapper.new)
|
110
112
|
|
113
|
+
@options[:base] = RDF::URI(@options[:base]) if @options[:base] && !@options[:base].is_a?(RDF::URI)
|
111
114
|
# For context via Link header
|
112
115
|
_, context_ref = nil, nil
|
113
116
|
|
@@ -117,7 +120,7 @@ module JSON::LD
|
|
117
120
|
remote_doc = self.class.loadRemoteDocument(input, **@options)
|
118
121
|
|
119
122
|
context_ref = remote_doc.contextUrl
|
120
|
-
@options[:base] = remote_doc.documentUrl if remote_doc.documentUrl && !@options[:no_default_base]
|
123
|
+
@options[:base] = RDF::URI(remote_doc.documentUrl) if remote_doc.documentUrl && !@options[:no_default_base]
|
121
124
|
|
122
125
|
case remote_doc.document
|
123
126
|
when String
|
@@ -130,7 +133,7 @@ module JSON::LD
|
|
130
133
|
|
131
134
|
# If not provided, first use context from document, or from a Link header
|
132
135
|
context ||= context_ref || {}
|
133
|
-
@context = Context.parse(context
|
136
|
+
@context = Context.parse(context, **@options)
|
134
137
|
|
135
138
|
if block_given?
|
136
139
|
case block.arity
|
@@ -163,10 +166,9 @@ module JSON::LD
|
|
163
166
|
# If a block is given, the result of evaluating the block is returned, otherwise, the expanded JSON-LD document
|
164
167
|
# @see https://www.w3.org/TR/json-ld11-api/#expansion-algorithm
|
165
168
|
def self.expand(input, framing: false, **options, &block)
|
166
|
-
result
|
169
|
+
result = doc_base = nil
|
167
170
|
API.new(input, options[:expandContext], **options) do
|
168
171
|
result = self.expand(self.value, nil, self.context,
|
169
|
-
ordered: @options[:ordered],
|
170
172
|
framing: framing)
|
171
173
|
doc_base = @options[:base]
|
172
174
|
end
|
@@ -218,21 +220,21 @@ module JSON::LD
|
|
218
220
|
# 1) Perform the Expansion Algorithm on the JSON-LD input.
|
219
221
|
# This removes any existing context to allow the given context to be cleanly applied.
|
220
222
|
expanded_input = expanded ? input : API.expand(input, ordered: false, **options) do |res, base_iri|
|
221
|
-
options[:base] ||= base_iri if options[:compactToRelative]
|
223
|
+
options[:base] ||= RDF::URI(base_iri) if base_iri && options[:compactToRelative]
|
222
224
|
res
|
223
225
|
end
|
224
226
|
|
225
227
|
API.new(expanded_input, context, no_default_base: true, **options) do
|
226
228
|
log_debug(".compact") {"expanded input: #{expanded_input.to_json(JSON_STATE) rescue 'malformed json'}"}
|
227
|
-
result = compact(value
|
229
|
+
result = compact(value)
|
228
230
|
|
229
231
|
# xxx) Add the given context to the output
|
230
|
-
ctx = self.context.serialize
|
232
|
+
ctx = self.context.serialize(provided_context: context)
|
231
233
|
if result.is_a?(Array)
|
232
234
|
kwgraph = self.context.compact_iri('@graph', vocab: true)
|
233
235
|
result = result.empty? ? {} : {kwgraph => result}
|
234
236
|
end
|
235
|
-
result = ctx.merge(result) unless ctx.empty?
|
237
|
+
result = ctx.merge(result) unless ctx.fetch('@context', {}).empty?
|
236
238
|
end
|
237
239
|
block_given? ? yield(result) : result
|
238
240
|
end
|
@@ -265,7 +267,7 @@ module JSON::LD
|
|
265
267
|
|
266
268
|
# Expand input to simplify processing
|
267
269
|
expanded_input = expanded ? input : API.expand(input, **options) do |result, base_iri|
|
268
|
-
options[:base] ||= base_iri if options[:compactToRelative]
|
270
|
+
options[:base] ||= RDF::URI(base_iri) if base_iri && options[:compactToRelative]
|
269
271
|
result
|
270
272
|
end
|
271
273
|
|
@@ -294,9 +296,11 @@ module JSON::LD
|
|
294
296
|
|
295
297
|
if context && !flattened.empty?
|
296
298
|
# 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
|
-
compacted = as_array(compact(flattened
|
299
|
+
compacted = as_array(compact(flattened))
|
298
300
|
kwgraph = self.context.compact_iri('@graph')
|
299
|
-
flattened = self.context.
|
301
|
+
flattened = self.context.
|
302
|
+
serialize(provided_context: context).
|
303
|
+
merge(kwgraph => compacted)
|
300
304
|
end
|
301
305
|
end
|
302
306
|
|
@@ -335,7 +339,7 @@ module JSON::LD
|
|
335
339
|
def self.frame(input, frame, expanded: false, **options)
|
336
340
|
result = nil
|
337
341
|
options = {
|
338
|
-
base: (input if input.is_a?(String)),
|
342
|
+
base: (RDF::URI(input) if input.is_a?(String)),
|
339
343
|
compactArrays: true,
|
340
344
|
compactToRelative: true,
|
341
345
|
embed: '@once',
|
@@ -369,7 +373,7 @@ module JSON::LD
|
|
369
373
|
|
370
374
|
# Expand input to simplify processing
|
371
375
|
expanded_input = expanded ? input : API.expand(input, ordered: false, **options) do |res, base_iri|
|
372
|
-
options[:base] ||= base_iri if options[:compactToRelative]
|
376
|
+
options[:base] ||= RDF::URI(base_iri) if base_iri && options[:compactToRelative]
|
373
377
|
res
|
374
378
|
end
|
375
379
|
|
@@ -426,7 +430,7 @@ module JSON::LD
|
|
426
430
|
log_debug(".frame") {"expanded result: #{result.to_json(JSON_STATE) rescue 'malformed json'}"}
|
427
431
|
|
428
432
|
# Compact result
|
429
|
-
compacted = compact(result
|
433
|
+
compacted = compact(result)
|
430
434
|
|
431
435
|
# @replace `@null` with nil, compacting arrays
|
432
436
|
compacted = cleanup_null(compacted)
|
@@ -434,11 +438,14 @@ module JSON::LD
|
|
434
438
|
|
435
439
|
# Add the given context to the output
|
436
440
|
result = if !compacted.is_a?(Array)
|
437
|
-
|
441
|
+
compacted
|
438
442
|
else
|
439
443
|
kwgraph = context.compact_iri('@graph')
|
440
|
-
|
444
|
+
{kwgraph => compacted}
|
441
445
|
end
|
446
|
+
# Only add context if one was provided
|
447
|
+
result = context.serialize(provided_context: frame).merge(result) if frame['@context']
|
448
|
+
|
442
449
|
log_debug(".frame") {"after compact: #{result.to_json(JSON_STATE) rescue 'malformed json'}"}
|
443
450
|
result
|
444
451
|
end
|
@@ -521,8 +528,7 @@ module JSON::LD
|
|
521
528
|
API.new(nil, nil, **options) do
|
522
529
|
result = from_statements(input,
|
523
530
|
useRdfType: useRdfType,
|
524
|
-
useNativeTypes: useNativeTypes
|
525
|
-
ordered: @options[:ordered])
|
531
|
+
useNativeTypes: useNativeTypes)
|
526
532
|
end
|
527
533
|
|
528
534
|
block_given? ? yield(result) : result
|
@@ -532,16 +538,18 @@ module JSON::LD
|
|
532
538
|
# Uses built-in or provided documentLoader to retrieve a parsed document.
|
533
539
|
#
|
534
540
|
# @param [RDF::URI, String] url
|
541
|
+
# @param [String, RDF::URI] base
|
542
|
+
# Location to use as documentUrl instead of `url`.
|
543
|
+
# @option options [Proc] :documentLoader
|
544
|
+
# The callback of the loader to be used to retrieve remote documents and contexts.
|
535
545
|
# @param [Boolean] extractAllScripts
|
536
546
|
# If set to `true`, when extracting JSON-LD script elements from HTML, unless a specific fragment identifier is targeted, extracts all encountered JSON-LD script elements using an array form, if necessary.
|
537
547
|
# @param [String] profile
|
538
548
|
# When the resulting `contentType` is `text/html` or `application/xhtml+xml`, this option determines the profile to use for selecting a JSON-LD script elements.
|
539
549
|
# @param [String] requestProfile
|
540
550
|
# One or more IRIs to use in the request as a profile parameter.
|
541
|
-
# @param [Boolean] validate
|
551
|
+
# @param [Boolean] validate (false)
|
542
552
|
# Allow only appropriate content types
|
543
|
-
# @param [String, RDF::URI] base
|
544
|
-
# Location to use as documentUrl instead of `url`.
|
545
553
|
# @param [Hash<Symbol => Object>] options
|
546
554
|
# @yield remote_document
|
547
555
|
# @yieldparam [RemoteDocumentRemoteDocument, RDF::Util::File::RemoteDocument] remote_document
|
@@ -550,13 +558,14 @@ module JSON::LD
|
|
550
558
|
# If a block is given, the result of evaluating the block is returned, otherwise, the retrieved remote document and context information unless block given
|
551
559
|
# @raise [JsonLdError]
|
552
560
|
def self.loadRemoteDocument(url,
|
561
|
+
base: nil,
|
562
|
+
documentLoader: nil,
|
553
563
|
extractAllScripts: false,
|
554
564
|
profile: nil,
|
555
565
|
requestProfile: nil,
|
556
566
|
validate: false,
|
557
|
-
base: nil,
|
558
567
|
**options)
|
559
|
-
documentLoader
|
568
|
+
documentLoader ||= self.method(:documentLoader)
|
560
569
|
options = OPEN_OPTS.merge(options)
|
561
570
|
if requestProfile
|
562
571
|
# Add any request profile
|
@@ -703,14 +712,14 @@ module JSON::LD
|
|
703
712
|
require "json/ld/html/#{library}"
|
704
713
|
|
705
714
|
# Parse HTML using the appropriate library
|
706
|
-
|
715
|
+
implementation = case library
|
707
716
|
when :nokogiri then Nokogiri
|
708
717
|
when :rexml then REXML
|
709
718
|
end
|
710
|
-
self.extend(
|
719
|
+
self.extend(implementation)
|
711
720
|
|
712
721
|
input = begin
|
713
|
-
|
722
|
+
self.send("initialize_html_#{library}".to_sym, input, **options)
|
714
723
|
rescue
|
715
724
|
raise JSON::LD::JsonLdError::LoadingDocumentFailed, "Malformed HTML document: #{$!.message}"
|
716
725
|
end
|
@@ -729,8 +738,8 @@ module JSON::LD
|
|
729
738
|
id = CGI.unescape(url.fragment)
|
730
739
|
# Find script with an ID based on that fragment.
|
731
740
|
element = input.at_xpath("//script[@id='#{id}']")
|
732
|
-
raise JSON::LD::JsonLdError::
|
733
|
-
raise JSON::LD::JsonLdError::
|
741
|
+
raise JSON::LD::JsonLdError::LoadingDocumentFailed, "No script tag found with id=#{id}" unless element
|
742
|
+
raise JSON::LD::JsonLdError::LoadingDocumentFailed, "Script tag has type=#{element.attributes['type']}" unless element.attributes['type'].to_s.start_with?('application/ld+json')
|
734
743
|
content = element.inner_html
|
735
744
|
validate_input(content, url: url) if options[:validate]
|
736
745
|
MultiJson.load(content, **options)
|
@@ -759,11 +768,12 @@ module JSON::LD
|
|
759
768
|
# Find the first script with type application/ld+json.
|
760
769
|
element = input.at_xpath("//script[starts-with(@type, 'application/ld+json;profile=#{profile}')]") if profile
|
761
770
|
element ||= input.at_xpath("//script[starts-with(@type, 'application/ld+json')]")
|
762
|
-
|
771
|
+
raise JSON::LD::JsonLdError::LoadingDocumentFailed, "No script tag found" unless element
|
772
|
+
content = element.inner_html
|
763
773
|
validate_input(content, url: url) if options[:validate]
|
764
774
|
MultiJson.load(content, **options)
|
765
775
|
end
|
766
|
-
rescue
|
776
|
+
rescue MultiJson::ParseError => e
|
767
777
|
raise JSON::LD::JsonLdError::InvalidScriptElement, e.message
|
768
778
|
end
|
769
779
|
|
data/lib/json/ld/compact.rb
CHANGED
@@ -12,16 +12,16 @@ module JSON::LD
|
|
12
12
|
# This algorithm compacts a JSON-LD document, such that the given context is applied. This must result in shortening any applicable IRIs to terms or compact IRIs, any applicable keywords to keyword aliases, and any applicable JSON-LD values expressed in expanded form to simple values such as strings or numbers.
|
13
13
|
#
|
14
14
|
# @param [Array, Hash] element
|
15
|
-
# @param [String]
|
16
|
-
# @param [Boolean] ordered (true)
|
15
|
+
# @param [String, RDF::URI] base (nil)
|
17
16
|
# Ensure output objects have keys ordered properly
|
17
|
+
# @param [String] property (nil)
|
18
|
+
# Extra validatation
|
18
19
|
# @return [Array, Hash]
|
19
|
-
def compact(element,
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
#end
|
20
|
+
def compact(element,
|
21
|
+
base: nil,
|
22
|
+
property: nil,
|
23
|
+
log_depth: nil)
|
24
|
+
log_debug("compact", depth: log_depth.to_i) {"element: #{element.inspect}, ec: #{context.inspect}"}
|
25
25
|
|
26
26
|
# If the term definition for active property itself contains a context, use that for compacting values.
|
27
27
|
input_context = self.context
|
@@ -29,17 +29,19 @@ module JSON::LD
|
|
29
29
|
case element
|
30
30
|
when Array
|
31
31
|
#log_debug("") {"Array #{element.inspect}"}
|
32
|
-
result = element.map
|
32
|
+
result = element.map do |item|
|
33
|
+
compact(item, base: base, property: property, log_depth: log_depth.to_i + 1)
|
34
|
+
end.compact
|
33
35
|
|
34
36
|
# If element has a single member and the active property has no
|
35
37
|
# @container mapping to @list or @set, the compacted value is that
|
36
38
|
# member; otherwise the compacted value is element
|
37
39
|
if result.length == 1 &&
|
38
40
|
!context.as_array?(property) && @options[:compactArrays]
|
39
|
-
|
41
|
+
log_debug("=> extract single element", depth: log_depth.to_i) {result.first.inspect}
|
40
42
|
result.first
|
41
43
|
else
|
42
|
-
|
44
|
+
log_debug("=> array result", depth: log_depth.to_i) {result.inspect}
|
43
45
|
result
|
44
46
|
end
|
45
47
|
when Hash
|
@@ -50,24 +52,31 @@ module JSON::LD
|
|
50
52
|
|
51
53
|
# Revert any previously type-scoped (non-preserved) context
|
52
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}"}
|
53
56
|
self.context = context.previous_context
|
54
57
|
end
|
55
58
|
|
56
59
|
# Look up term definintions from property using the original type-scoped context, if it exists, but apply them to the now current previous context
|
57
60
|
td = input_context.term_definitions[property] if property
|
58
|
-
|
61
|
+
if td && !td.context.nil?
|
62
|
+
self.context = context.parse(td.context,
|
63
|
+
override_protected: true)
|
64
|
+
log_debug("prop-scoped", depth: log_depth.to_i) {"context: #{self.context.inspect}"}
|
65
|
+
end
|
59
66
|
|
60
67
|
if element.key?('@id') || element.key?('@value')
|
61
|
-
result = context.compact_value(property, element,
|
68
|
+
result = context.compact_value(property, element, base: @options[:base])
|
62
69
|
if !result.is_a?(Hash) || context.coerce(property) == '@json'
|
63
|
-
|
70
|
+
log_debug("", depth: log_depth.to_i) {"=> scalar result: #{result.inspect}"}
|
64
71
|
return result
|
65
72
|
end
|
66
73
|
end
|
67
74
|
|
68
75
|
# If expanded property is @list and we're contained within a list container, recursively compact this item to an array
|
69
76
|
if list?(element) && context.container(property).include?('@list')
|
70
|
-
return compact(element['@list'],
|
77
|
+
return compact(element['@list'], base: base,
|
78
|
+
property: property,
|
79
|
+
log_depth: log_depth.to_i + 1)
|
71
80
|
end
|
72
81
|
|
73
82
|
inside_reverse = property == '@reverse'
|
@@ -80,15 +89,18 @@ module JSON::LD
|
|
80
89
|
sort.
|
81
90
|
each do |term|
|
82
91
|
term_context = input_context.term_definitions[term].context if input_context.term_definitions[term]
|
83
|
-
self.context = context.parse(term_context, propagate: false)
|
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}"}
|
84
94
|
end
|
85
95
|
|
86
|
-
element.keys.opt_sort(ordered: ordered).each do |expanded_property|
|
96
|
+
element.keys.opt_sort(ordered: @options[:ordered]).each do |expanded_property|
|
87
97
|
expanded_value = element[expanded_property]
|
88
|
-
|
98
|
+
log_debug("", depth: log_depth.to_i) {"#{expanded_property}: #{expanded_value.inspect}"}
|
89
99
|
|
90
100
|
if expanded_property == '@id'
|
91
|
-
compacted_value = Array(expanded_value).map
|
101
|
+
compacted_value = Array(expanded_value).map do |expanded_id|
|
102
|
+
context.compact_iri(expanded_id, base: @options[:base])
|
103
|
+
end
|
92
104
|
|
93
105
|
kw_alias = context.compact_iri('@id', vocab: true)
|
94
106
|
as_array = compacted_value.length > 1
|
@@ -98,7 +110,9 @@ module JSON::LD
|
|
98
110
|
end
|
99
111
|
|
100
112
|
if expanded_property == '@type'
|
101
|
-
compacted_value = Array(expanded_value).map
|
113
|
+
compacted_value = Array(expanded_value).map do |expanded_type|
|
114
|
+
input_context.compact_iri(expanded_type, vocab: true)
|
115
|
+
end
|
102
116
|
|
103
117
|
kw_alias = context.compact_iri('@type', vocab: true)
|
104
118
|
as_array = compacted_value.length > 1 ||
|
@@ -110,8 +124,10 @@ module JSON::LD
|
|
110
124
|
end
|
111
125
|
|
112
126
|
if expanded_property == '@reverse'
|
113
|
-
compacted_value = compact(expanded_value,
|
114
|
-
|
127
|
+
compacted_value = compact(expanded_value, base: base,
|
128
|
+
property: '@reverse',
|
129
|
+
log_depth: log_depth.to_i + 1)
|
130
|
+
log_debug("@reverse", depth: log_depth.to_i) {"compacted_value: #{compacted_value.inspect}"}
|
115
131
|
# handle double-reversed properties
|
116
132
|
compacted_value.each do |prop, value|
|
117
133
|
if context.reverse?(prop)
|
@@ -123,7 +139,7 @@ module JSON::LD
|
|
123
139
|
|
124
140
|
unless compacted_value.empty?
|
125
141
|
al = context.compact_iri('@reverse')
|
126
|
-
|
142
|
+
log_debug("", depth: log_depth.to_i) {"remainder: #{al} => #{compacted_value.inspect}"}
|
127
143
|
result[al] = compacted_value
|
128
144
|
end
|
129
145
|
next
|
@@ -131,8 +147,10 @@ module JSON::LD
|
|
131
147
|
|
132
148
|
if expanded_property == '@preserve'
|
133
149
|
# Compact using `property`
|
134
|
-
compacted_value = compact(expanded_value,
|
135
|
-
|
150
|
+
compacted_value = compact(expanded_value, base: base,
|
151
|
+
property: property,
|
152
|
+
log_depth: log_depth.to_i + 1)
|
153
|
+
log_debug("@preserve", depth: log_depth.to_i) {"compacted_value: #{compacted_value.inspect}"}
|
136
154
|
|
137
155
|
unless compacted_value.is_a?(Array) && compacted_value.empty?
|
138
156
|
result['@preserve'] = compacted_value
|
@@ -141,14 +159,14 @@ module JSON::LD
|
|
141
159
|
end
|
142
160
|
|
143
161
|
if expanded_property == '@index' && context.container(property).include?('@index')
|
144
|
-
|
162
|
+
log_debug("@index", depth: log_depth.to_i) {"drop @index"}
|
145
163
|
next
|
146
164
|
end
|
147
165
|
|
148
166
|
# Otherwise, if expanded property is @direction, @index, @value, or @language:
|
149
167
|
if EXPANDED_PROPERTY_DIRECTION_INDEX_LANGUAGE_VALUE.include?(expanded_property)
|
150
168
|
al = context.compact_iri(expanded_property, vocab: true)
|
151
|
-
|
169
|
+
log_debug(expanded_property, depth: log_depth.to_i) {"#{al} => #{expanded_value.inspect}"}
|
152
170
|
result[al] = expanded_value
|
153
171
|
next
|
154
172
|
end
|
@@ -158,8 +176,7 @@ module JSON::LD
|
|
158
176
|
context.compact_iri(expanded_property,
|
159
177
|
value: expanded_value,
|
160
178
|
vocab: true,
|
161
|
-
reverse: inside_reverse
|
162
|
-
log_depth: @options[:log_depth])
|
179
|
+
reverse: inside_reverse)
|
163
180
|
|
164
181
|
if nest_prop = context.nest(item_active_property)
|
165
182
|
result[nest_prop] ||= {}
|
@@ -177,8 +194,7 @@ module JSON::LD
|
|
177
194
|
context.compact_iri(expanded_property,
|
178
195
|
value: expanded_item,
|
179
196
|
vocab: true,
|
180
|
-
reverse: inside_reverse
|
181
|
-
log_depth: @options[:log_depth])
|
197
|
+
reverse: inside_reverse)
|
182
198
|
|
183
199
|
|
184
200
|
nest_result = if nest_prop = context.nest(item_active_property)
|
@@ -197,8 +213,10 @@ module JSON::LD
|
|
197
213
|
else expanded_item
|
198
214
|
end
|
199
215
|
|
200
|
-
compacted_item = compact(value,
|
201
|
-
|
216
|
+
compacted_item = compact(value, base: base,
|
217
|
+
property: item_active_property,
|
218
|
+
log_depth: log_depth.to_i + 1)
|
219
|
+
log_debug("", depth: log_depth.to_i) {" => compacted key: #{item_active_property.inspect} for #{compacted_item.inspect}"}
|
202
220
|
|
203
221
|
# handle @list
|
204
222
|
if list?(expanded_item)
|
@@ -225,9 +243,9 @@ module JSON::LD
|
|
225
243
|
map_object = nest_result[item_active_property] ||= {}
|
226
244
|
# If there is no @id, create a blank node identifier to use as an index
|
227
245
|
map_key = if container.include?('@id') && expanded_item['@id']
|
228
|
-
context.compact_iri(expanded_item['@id'])
|
246
|
+
context.compact_iri(expanded_item['@id'], base: @options[:base])
|
229
247
|
elsif container.include?('@index') && expanded_item['@index']
|
230
|
-
context.compact_iri(expanded_item['@index'])
|
248
|
+
context.compact_iri(expanded_item['@index'], vocab: true)
|
231
249
|
else
|
232
250
|
context.compact_iri('@none', vocab: true)
|
233
251
|
end
|
@@ -299,7 +317,10 @@ module JSON::LD
|
|
299
317
|
|
300
318
|
# if compacted_item contains a single entry who's key maps to @id, then recompact the item without @type
|
301
319
|
if compacted_item.keys.length == 1 && expanded_item.keys.include?('@id')
|
302
|
-
compacted_item = compact({'@id' => expanded_item['@id']},
|
320
|
+
compacted_item = compact({'@id' => expanded_item['@id']},
|
321
|
+
base: base,
|
322
|
+
property: item_active_property,
|
323
|
+
log_depth: log_depth.to_i + 1)
|
303
324
|
end
|
304
325
|
compacted_item
|
305
326
|
end
|
@@ -316,7 +337,7 @@ module JSON::LD
|
|
316
337
|
result
|
317
338
|
else
|
318
339
|
# For other types, the compacted value is the element value
|
319
|
-
|
340
|
+
log_debug("compact", depth: log_depth.to_i) {element.class.to_s}
|
320
341
|
element
|
321
342
|
end
|
322
343
|
|