Skip to content

Commit 7332ad6

Browse files
committed
Finish 2.1.5
2 parents 9665d09 + 6d11bd2 commit 7332ad6

15 files changed

+370
-112
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.1.4
1+
2.1.5

bin/jsonld

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ OPT_ARGS = [
115115
["--quiet", GetoptLong::NO_ARGUMENT, "Supress most output other than progress indicators"],
116116
["--rename_bnodes", GetoptLong::OPTIONAL_ARGUMENT,"Rename bnodes as part of expansion, or keep them the same"],
117117
["--requireAll", GetoptLong::OPTIONAL_ARGUMENT,"Rename bnodes as part of expansion, or keep them the same"],
118-
["--simple_compact_iris",GetoptLong::OPTIONAL_ARGUMENT,"When compacting IRIs, do not use terms with expanded term definitions"],
119118
["--stream", GetoptLong::NO_ARGUMENT, "Use Streaming reader/writer"],
120119
["--unique_bnodes", GetoptLong::OPTIONAL_ARGUMENT,"Use unique bnode identifiers"],
121120
["--uri", GetoptLong::REQUIRED_ARGUMENT,"URI to be used as the document base"],

example-files/issue-507.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
require 'pp'
2+
require 'linkeddata'
3+
4+
context = JSON.parse %({
5+
"@context": {
6+
"id": "@id",
7+
"rdfs": {"@id": "http://.../"},
8+
"seeAlso": {"@id": "rdfs:seeAlso", "@container": "@set"}
9+
}
10+
})
11+
12+
input = JSON.parse %({
13+
"@context": {
14+
"id": "@id",
15+
"rdfs": {"@id": "http://.../"},
16+
"seeAlso": {"@id": "rdfs:seeAlso", "@container": "@set"}
17+
},
18+
"seeAlso": [
19+
{
20+
"id": "http://example.org/reference1"
21+
},
22+
"http://example.org/reference2",
23+
{"id": "http://example.org/reference3", "format": "text/html"}
24+
]
25+
})
26+
27+
pp JSON::LD::API.compact(input, context['@context'])

example-files/pr-509.jsonld

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"@context": {
3+
"name": {
4+
"@type": "@id",
5+
"@container": "@list",
6+
"@id": "https://schema.org/name"
7+
}
8+
},
9+
"name": []
10+
}

json-ld.gemspec

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ Gem::Specification.new do |gem|
2929
gem.requirements = []
3030
gem.add_runtime_dependency 'rdf', '~> 2.2'
3131
gem.add_runtime_dependency 'multi_json', '~> 1.12'
32-
gem.add_development_dependency 'linkeddata', '~> 2.0'
33-
gem.add_development_dependency 'jsonlint', '~> 0.2' unless RUBY_ENGINE == "jruby"
34-
gem.add_development_dependency 'oj', '~> 2.17' unless RUBY_ENGINE == "jruby"
35-
gem.add_development_dependency 'yajl-ruby', '~> 1.2' unless RUBY_ENGINE == "jruby"
32+
gem.add_development_dependency 'linkeddata', '~> 2.2'
33+
gem.add_development_dependency 'jsonlint', '~> 0.2' unless RUBY_ENGINE == "jruby"
34+
gem.add_development_dependency 'oj', '~> 2.17' unless RUBY_ENGINE == "jruby"
35+
gem.add_development_dependency 'yajl-ruby', '~> 1.2' unless RUBY_ENGINE == "jruby"
3636
gem.add_development_dependency 'rdf-isomorphic', '~> 2.0'
3737
gem.add_development_dependency 'rdf-spec', '~> 2.2'
3838
gem.add_development_dependency 'rdf-trig', '~> 2.0'

lib/json/ld.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class InvalidLanguageTaggedString < JsonLdError; @code = "invalid language-tagge
115115
class InvalidLanguageTaggedValue < JsonLdError; @code = "invalid language-tagged value"; end
116116
class InvalidLocalContext < JsonLdError; @code = "invalid local context"; end
117117
class InvalidNestValue < JsonLdError; @code = "invalid @nest value"; end
118+
class InvalidPrefixValue < JsonLdError; @code = "invalid @prefix value"; end
118119
class InvalidRemoteContext < JsonLdError; @code = "invalid remote context"; end
119120
class InvalidReverseProperty < JsonLdError; @code = "invalid reverse property"; end
120121
class InvalidReversePropertyMap < JsonLdError; @code = "invalid reverse property map"; end

lib/json/ld/api.rb

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ class API
6363
# 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.
6464
# @option options [Boolean] :compactArrays (true)
6565
# 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.
66+
# @option options [Boolean] :compactToRelative (true)
67+
# Creates document relative IRIs when compacting, if `true`, otherwise leaves expanded.
6668
# @option options [Proc] :documentLoader
6769
# 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 {documentLoader} for the method signature.
6870
# @option options [String, #read, Hash, Array, JSON::LD::Context] :expandContext
@@ -79,29 +81,26 @@ class API
7981
# Rename bnodes as part of expansion, or keep them the same.
8082
# @option options [Boolean] :unique_bnodes (false)
8183
# Use unique bnode identifiers, defaults to using the identifier which the node was originally initialized with (if any).
82-
# @option options [Boolean] :simple_compact_iris (false)
83-
# When compacting IRIs, do not use terms with expanded term definitions
8484
# @option options [Symbol] :adapter used with MultiJson
8585
# @option options [Boolean] :validate Validate input, if a string or readable object.
8686
# @yield [api]
8787
# @yieldparam [API]
8888
# @raise [JsonLdError]
8989
def initialize(input, context, options = {}, &block)
9090
@options = {
91-
compactArrays: true,
92-
rename_bnodes: true,
93-
documentLoader: self.class.method(:documentLoader)
94-
}
95-
@options = @options.merge(options)
91+
compactArrays: true,
92+
rename_bnodes: true,
93+
documentLoader: self.class.method(:documentLoader)
94+
}.merge(options)
9695
@namer = options[:unique_bnodes] ? BlankNodeUniqer.new : (@options[:rename_bnodes] ? BlankNodeNamer.new("b") : BlankNodeMapper.new)
9796

9897
# For context via Link header
99-
context_ref = nil
98+
remote_base, context_ref = nil, nil
10099

101100
@value = case input
102101
when Array, Hash then input.dup
103102
when IO, StringIO
104-
@options = {base: input.base_uri}.merge!(@options) if input.respond_to?(:base_uri)
103+
@options = {base: input.base_uri}.merge(@options) if input.respond_to?(:base_uri)
105104

106105
# if input impelements #links, attempt to get a contextUrl from that link
107106
content_type = input.respond_to?(:content_type) ? input.content_type : "application/json"
@@ -116,8 +115,9 @@ def initialize(input, context, options = {}, &block)
116115
when String
117116
remote_doc = @options[:documentLoader].call(input, @options)
118117

119-
@options = {base: remote_doc.documentUrl}.merge!(@options)
118+
remote_base = remote_doc.documentUrl
120119
context_ref = remote_doc.contextUrl
120+
@options = {base: remote_doc.documentUrl}.merge(@options) unless @options[:no_default_base]
121121

122122
case remote_doc.document
123123
when String
@@ -128,9 +128,6 @@ def initialize(input, context, options = {}, &block)
128128
end
129129
end
130130

131-
# Update calling context :base option, if not defined
132-
options[:base] ||= @options[:base] if @options[:base]
133-
134131
# If not provided, first use context from document, or from a Link header
135132
context ||= (@value['@context'] if @value.is_a?(Hash)) || context_ref
136133
@context = Context.parse(context || {}, @options)
@@ -160,25 +157,38 @@ def initialize(input, context, options = {}, &block)
160157
# @param [Hash{Symbol => Object}] options
161158
# @option options (see #initialize)
162159
# @raise [JsonLdError]
163-
# @yield jsonld
160+
# @yield jsonld, base_iri
164161
# @yieldparam [Array<Hash>] jsonld
165162
# The expanded JSON-LD document
163+
# @yieldparam [RDF::URI] base_iri
164+
# The document base as determined during expansion
166165
# @yieldreturn [Object] returned object
167166
# @return [Object, Array<Hash>]
168167
# If a block is given, the result of evaluating the block is returned, otherwise, the expanded JSON-LD document
169168
# @see http://json-ld.org/spec/latest/json-ld-api/#expansion-algorithm
170-
def self.expand(input, options = {})
171-
result = nil
172-
API.new(input, options[:expandContext], options) do |api|
173-
result = api.expand(api.value, nil, api.context, ordered: options.fetch(:ordered, true))
169+
def self.expand(input, options = {}, &block)
170+
result, doc_base = nil
171+
API.new(input, options[:expandContext], options) do
172+
result = self.expand(self.value, nil, self.context, ordered: options.fetch(:ordered, true))
173+
doc_base = @options[:base]
174174
end
175175

176176
# If, after the algorithm outlined above is run, the resulting element is an JSON object with just a @graph property, element is set to the value of @graph's value.
177177
result = result['@graph'] if result.is_a?(Hash) && result.keys == %w(@graph)
178178

179179
# Finally, if element is a JSON object, it is wrapped into an array.
180180
result = [result].compact unless result.is_a?(Array)
181-
block_given? ? yield(result) : result
181+
182+
if block_given?
183+
case block.arity
184+
when 1 then yield(result)
185+
when 2 then yield(result, doc_base)
186+
else
187+
raise "Unexpected number of yield parameters to expand"
188+
end
189+
else
190+
result
191+
end
182192
end
183193

184194
##
@@ -204,13 +214,17 @@ def self.expand(input, options = {})
204214
# @raise [JsonLdError]
205215
# @see http://json-ld.org/spec/latest/json-ld-api/#compaction-algorithm
206216
def self.compact(input, context, options = {})
207-
expanded = result = nil
217+
result = nil
218+
options = {compactToRelative: true}.merge(options)
208219

209220
# 1) Perform the Expansion Algorithm on the JSON-LD input.
210221
# This removes any existing context to allow the given context to be cleanly applied.
211-
expanded_input = options[:expanded] ? input : API.expand(input, options)
222+
expanded_input = options[:expanded] ? input : API.expand(input, options) do |result, base_iri|
223+
options[:base] ||= base_iri if options[:compactToRelative]
224+
result
225+
end
212226

213-
API.new(expanded_input, context, options) do
227+
API.new(expanded_input, context, options.merge(no_default_base: true)) do
214228
log_debug(".compact") {"expanded input: #{expanded_input.to_json(JSON_STATE) rescue 'malformed json'}"}
215229
result = compact(value)
216230

@@ -246,12 +260,16 @@ def self.compact(input, context, options = {})
246260
# @see http://json-ld.org/spec/latest/json-ld-api/#framing-algorithm
247261
def self.flatten(input, context, options = {})
248262
flattened = []
263+
options = {compactToRelative: true}.merge(options)
249264

250265
# Expand input to simplify processing
251-
expanded_input = options[:expanded] ? input : API.expand(input, options)
266+
expanded_input = options[:expanded] ? input : API.expand(input, options) do |result, base_iri|
267+
options[:base] ||= base_iri if options[:compactToRelative]
268+
result
269+
end
252270

253271
# Initialize input using
254-
API.new(expanded_input, context, options) do
272+
API.new(expanded_input, context, options.merge(no_default_base: true)) do
255273
log_debug(".flatten") {"expanded input: #{value.to_json(JSON_STATE) rescue 'malformed json'}"}
256274

257275
# Initialize node map to a JSON object consisting of a single member whose key is @default and whose value is an empty JSON object.
@@ -316,13 +334,14 @@ def self.frame(input, frame, options = {})
316334
options = {
317335
base: (input if input.is_a?(String)),
318336
compactArrays: true,
337+
compactToRelative: true,
319338
embed: '@last',
320339
explicit: false,
321340
requireAll: true,
322341
omitDefault: false,
323342
pruneBlankNodeIdentifiers: true,
324343
documentLoader: method(:documentLoader)
325-
}.merge!(options)
344+
}.merge(options)
326345

327346
framing_state = {
328347
graphMap: {},
@@ -344,13 +363,16 @@ def self.frame(input, frame, options = {})
344363
end
345364

346365
# Expand input to simplify processing
347-
expanded_input = options[:expanded] ? input : API.expand(input, options)
366+
expanded_input = options[:expanded] ? input : API.expand(input, options) do |result, base_iri|
367+
options[:base] ||= base_iri if options[:compactToRelative]
368+
result
369+
end
348370

349371
# Expand frame to simplify processing
350372
expanded_frame = API.expand(frame, options.merge(processingMode: "json-ld-1.1-expand-frame"))
351373

352374
# Initialize input using frame as context
353-
API.new(expanded_input, nil, options) do
375+
API.new(expanded_input, nil, options.merge(no_default_base: true)) do
354376
log_debug(".frame") {"expanded frame: #{expanded_frame.to_json(JSON_STATE) rescue 'malformed json'}"}
355377

356378
# Get framing nodes from expanded input, replacing Blank Node identifiers as necessary

0 commit comments

Comments
 (0)