json-ld 3.1.1 → 3.1.6
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/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
|
|