Skip to content

Commit

Permalink
Finish 3.1.10
Browse files Browse the repository at this point in the history
  • Loading branch information
gkellogg committed Sep 26, 2021
2 parents 737f015 + 7d02c9c commit a2c6020
Show file tree
Hide file tree
Showing 13 changed files with 221 additions and 58 deletions.
11 changes: 7 additions & 4 deletions .github/workflows/ci.yml
Expand Up @@ -22,12 +22,11 @@ jobs:
runs-on: ubuntu-latest
env:
CI: true
ALLOW_FAILURES: false ${{ endsWith(matrix.ruby, 'head') }}
ALLOW_FAILURES: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'jruby' }}
strategy:
fail-fast: false
matrix:
ruby:
- 2.4
- 2.5
- 2.6
- 2.7
Expand All @@ -44,5 +43,9 @@ jobs:
- name: Install dependencies
run: bundle install --jobs 4 --retry 3
- name: Run tests
run: bundle exec rspec spec || $ALLOW_FAILURES

run: ruby --version; bundle exec rspec spec || $ALLOW_FAILURES
- name: Coveralls GitHub Action
uses: coverallsapp/github-action@v1.1.2
if: "matrix.ruby == '3.0'"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
16 changes: 0 additions & 16 deletions .travis.yml

This file was deleted.

5 changes: 2 additions & 3 deletions Gemfile
@@ -1,6 +1,5 @@
source "https://rubygems.org"
gem "nokogiri", '~> 1.10'
gem "nokogumbo", platforms: :mri

gemspec
gem 'rdf', git: "https://github.com/ruby-rdf/rdf", branch: "develop"
Expand Down Expand Up @@ -38,8 +37,8 @@ group :development do
end

group :development, :test do
gem 'simplecov', platforms: :mri
gem 'coveralls', '~> 0.8', platforms: :mri
gem 'simplecov', '~> 0.21', platforms: :mri
gem 'simplecov-lcov', '~> 0.8', platforms: :mri
gem 'psych', platforms: [:mri, :rbx]
gem 'benchmark-ips'
gem 'rake'
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -14,7 +14,7 @@ JSON::LD parses and serializes [JSON-LD][] into [RDF][] and implements expansion
JSON::LD can now be used to create a _context_ from an RDFS/OWL definition, and optionally include a JSON-LD representation of the ontology itself. This is currently accessed through the `script/gen_context` script.

* If the [jsonlint][] gem is installed, it will be used when validating an input document.
* If available, uses [Nokogiri][] and/or [Nokogumbo][] for parsing HTML, falls back to REXML otherwise.
* If available, uses [Nokogiri][] for parsing HTML, falls back to REXML otherwise.
* Provisional support for [JSON-LD-star][JSON-LD-star].

[Implementation Report](https://ruby-rdf.github.io/json-ld/etc/earl.html)
Expand Down
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
3.1.9
3.1.10
1 change: 1 addition & 0 deletions lib/json/ld/compact.rb
Expand Up @@ -297,6 +297,7 @@ def compact(element,
if index_key == '@index'
map_key = expanded_item['@index']
else
index_key = context.expand_iri(index_key, vocab: true)
container_key = context.compact_iri(index_key, vocab: true)
map_key, *others = Array(compacted_item[container_key])
if map_key.is_a?(String)
Expand Down
28 changes: 16 additions & 12 deletions lib/json/ld/context.rb
Expand Up @@ -253,6 +253,7 @@ def parse(local_context,

local_context = as_array(local_context)

log_depth do
local_context.each do |context|
case context
when nil,false
Expand All @@ -266,22 +267,22 @@ def parse(local_context,
"Attempt to clear a context with protected terms"
end
when Context
#log_debug("parse") {"context: #{context.inspect}"}
log_debug("parse") {"context: #{context.inspect}"}
result = result.merge(context)
when IO, StringIO
#log_debug("parse") {"io: #{context}"}
log_debug("parse") {"io: #{context}"}
# Load context document, if it is an open file
begin
ctx = JSON.load(context)
raise JSON::LD::JsonLdError::InvalidRemoteContext, "Context missing @context key" if @options[:validate] && ctx['@context'].nil?
result = result.parse(ctx["@context"] ? ctx["@context"] : {})
rescue JSON::ParserError => e
#log_debug("parse") {"Failed to parse @context from remote document at #{context}: #{e.message}"}
log_info("parse") {"Failed to parse @context from remote document at #{context}: #{e.message}"}
raise JSON::LD::JsonLdError::InvalidRemoteContext, "Failed to parse remote context at #{context}: #{e.message}" if @options[:validate]
self
end
when String, RDF::URI
#log_debug("parse") {"remote: #{context}, base: #{result.context_base || result.base}"}
log_debug("parse") {"remote: #{context}, base: #{result.context_base || result.base}"}

# 3.2.1) Set context to the result of resolving value against the base IRI which is established as specified in section 5.1 Establishing a Base URI of [RFC3986]. Only the basic algorithm in section 5.2 of [RFC3986] is used; neither Syntax-Based Normalization nor Scheme-Based Normalization are performed. Characters additionally allowed in IRI references are treated in the same way that unreserved characters are treated in URI references, per section 6.5 of [RFC3987].
context = RDF::URI(result.context_base || base).join(context)
Expand All @@ -296,11 +297,11 @@ def parse(local_context,

cached_context = if PRELOADED[context_canon.to_s]
# If we have a cached context, merge it into the current context (result) and use as the new context
#log_debug("parse") {"=> cached_context: #{context_canon.to_s.inspect}"}
log_debug("parse") {"=> cached_context: #{context_canon.to_s.inspect}"}

# If this is a Proc, then replace the entry with the result of running the Proc
if PRELOADED[context_canon.to_s].respond_to?(:call)
#log_debug("parse") {"=> (call)"}
log_debug("parse") {"=> (call)"}
PRELOADED[context_canon.to_s] = PRELOADED[context_canon.to_s].call
end
PRELOADED[context_canon.to_s]
Expand All @@ -320,16 +321,17 @@ def parse(local_context,
ctx = Context.new(unfrozen: true, **options).dup
ctx.context_base = context.to_s
ctx = ctx.parse(remote_doc.document['@context'], remote_contexts: remote_contexts.dup)
ctx.context_base = context.to_s # In case it was altered
ctx.instance_variable_set(:@base, nil)
ctx
end
rescue JsonLdError::LoadingDocumentFailed => e
#log_debug("parse") {"Failed to retrieve @context from remote document at #{context_no_base.context_base.inspect}: #{e.message}"}
log_info("parse") {"Failed to retrieve @context from remote document at #{context_canon.inspect}: #{e.message}"}
raise JsonLdError::LoadingRemoteContextFailed, "#{context}: #{e.message}", e.backtrace
rescue JsonLdError
raise
rescue StandardError => e
#log_debug("parse") {"Failed to retrieve @context from remote document at #{context_no_base.context_base.inspect}: #{e.message}"}
log_info("parse") {"Failed to retrieve @context from remote document at #{context_canon.inspect}: #{e.message}"}
raise JsonLdError::LoadingRemoteContextFailed, "#{context}: #{e.message}", e.backtrace
end
end
Expand Down Expand Up @@ -406,6 +408,7 @@ def parse(local_context,
raise JsonLdError::InvalidLocalContext, "must be a URL, JSON object or array of same: #{context.inspect}"
end
end
end
result
end

Expand Down Expand Up @@ -475,7 +478,7 @@ def create_term_definition(local_context, term, defined,
remote_contexts: [],
validate_scoped: true)
# Expand a string value, unless it matches a keyword
#log_debug("create_term_definition") {"term = #{term.inspect}"}
log_debug("create_term_definition") {"term = #{term.inspect}"}

# If defined contains the key term, then the associated value must be true, indicating that the term definition has already been created, so return. Otherwise, a cyclical term definition has been detected, which is an error.
case defined[term]
Expand Down Expand Up @@ -646,7 +649,7 @@ def create_term_definition(local_context, term, defined,
# Otherwise, term is an absolute IRI. Set the IRI mapping for definition to term
term
end
#log_debug("") {"=> #{definition.id}"}
log_debug("") {"=> #{definition.id}"}
elsif term.include?('/')
# If term is a relative IRI
definition.id = expand_iri(term, vocab: true)
Expand All @@ -659,7 +662,7 @@ def create_term_definition(local_context, term, defined,
# Otherwise, active context must have a vocabulary mapping, otherwise an invalid value has been detected, which is an error. Set the IRI mapping for definition to the result of concatenating the value associated with the vocabulary mapping and term.
raise JsonLdError::InvalidIRIMapping, "relative term definition without vocab: #{term} on term #{term.inspect}" unless vocab
definition.id = vocab + term
#log_debug("") {"=> #{definition.id}"}
log_debug("") {"=> #{definition.id}"}
end

@iri_to_term[definition.id] = term if simple_term && definition.id
Expand Down Expand Up @@ -699,6 +702,7 @@ def create_term_definition(local_context, term, defined,
when nil then [nil]
else value['@context']
end
log_debug("") {"context: #{definition.context.inspect}"}
rescue JsonLdError => e
raise JsonLdError::InvalidScopedContext, "Term definition for #{term.inspect} contains illegal value for @context: #{e.message}"
end
Expand Down Expand Up @@ -1884,7 +1888,7 @@ def remove_base(base, iri)
@base_and_parents ||= begin
u = base
iri_set = u.to_s.end_with?('/') ? [u.to_s] : []
iri_set << u.to_s while (u = u.parent)
iri_set << u.to_s while (u != './' && u = u.parent)
iri_set
end
b = base.to_s
Expand Down
22 changes: 11 additions & 11 deletions lib/json/ld/expand.rb
Expand Up @@ -107,7 +107,7 @@ def expand(input, active_property, context,
Array(input[tk]).sort.each do |term|
term_context = type_scoped_context.term_definitions[term].context if type_scoped_context.term_definitions[term]
unless term_context.nil?
log_debug("expand", depth: log_depth.to_i) {"term_context: #{term_context.inspect}"}
log_debug("expand", depth: log_depth.to_i) {"term_context[#{term}]: #{term_context.inspect}"}
context = context.parse(term_context, base: @options[:base], propagate: false)
end
end
Expand Down Expand Up @@ -258,10 +258,10 @@ def expand_object(input, active_property, context, output_object,
expanded_property.to_s.start_with?("_:") &&
context.processingMode('json-ld-1.1')

#log_debug("expand property", depth: log_depth.to_i) {"ap: #{active_property.inspect}, expanded: #{expanded_property.inspect}, value: #{value.inspect}"}
log_debug("expand property", depth: log_depth.to_i) {"ap: #{active_property.inspect}, expanded: #{expanded_property.inspect}, value: #{value.inspect}"}

if expanded_property.nil?
#log_debug(" => ", depth: log_depth.to_i) {"skip nil property"}
log_debug(" => ", depth: log_depth.to_i) {"skip nil property"}
next
end

Expand Down Expand Up @@ -341,7 +341,7 @@ def expand_object(input, active_property, context, output_object,
Array(output_object['@included']) + included_result
when '@type'
# If expanded property is @type and value is neither a string nor an array of strings, an invalid type value error has been detected and processing is aborted. Otherwise, set expanded value to the result of using the IRI Expansion algorithm, passing active context, true for vocab, and true for document relative to expand the value or each of its items.
#log_debug("@type", depth: log_depth.to_i) {"value: #{value.inspect}"}
log_debug("@type", depth: log_depth.to_i) {"value: #{value.inspect}"}
e_type = case value
when Array
value.map do |v|
Expand Down Expand Up @@ -516,7 +516,7 @@ def expand_object(input, active_property, context, output_object,

# If expanded value contains an @reverse member, i.e., properties that are reversed twice, execute for each of its property and item the following steps:
if value.key?('@reverse')
#log_debug("@reverse", depth: log_depth.to_i) {"double reverse: #{value.inspect}"}
log_debug("@reverse", depth: log_depth.to_i) {"double reverse: #{value.inspect}"}
value['@reverse'].each do |property, item|
# If result does not have a property member, create one and set its value to an empty array.
# Append item to the value of the property member of result.
Expand Down Expand Up @@ -566,7 +566,7 @@ def expand_object(input, active_property, context, output_object,
end

# Unless expanded value is null, set the expanded property member of result to expanded value.
#log_debug("expand #{expanded_property}", depth: log_depth.to_i) { expanded_value.inspect}
log_debug("expand #{expanded_property}", depth: log_depth.to_i) { expanded_value.inspect}
output_object[expanded_property] = expanded_value unless expanded_value.nil? && expanded_property == '@value' && input_type != '@json'
next
end
Expand Down Expand Up @@ -688,21 +688,21 @@ def expand_object(input, active_property, context, output_object,

# If expanded value is null, ignore key by continuing to the next key from element.
if expanded_value.nil?
#log_debug(" => skip nil value", depth: log_depth.to_i)
log_debug(" => skip nil value", depth: log_depth.to_i)
next
end
#log_debug(depth: log_depth.to_i) {" => #{expanded_value.inspect}"}
log_debug(depth: log_depth.to_i) {" => #{expanded_value.inspect}"}

# If the container mapping associated to key in active context is @list and expanded value is not already a list object, convert expanded value to a list object by first setting it to an array containing only expanded value if it is not already an array, and then by setting it to a JSON object containing the key-value pair @list-expanded value.
if container.first == '@list' && container.length == 1 && !list?(expanded_value)
#log_debug(" => ", depth: log_depth.to_i) { "convert #{expanded_value.inspect} to list"}
log_debug(" => ", depth: log_depth.to_i) { "convert #{expanded_value.inspect} to list"}
expanded_value = {'@list' => as_array(expanded_value)}
end
#log_debug(depth: log_depth.to_i) {" => #{expanded_value.inspect}"}
log_debug(depth: log_depth.to_i) {" => #{expanded_value.inspect}"}

# convert expanded value to @graph if container specifies it
if container.first == '@graph' && container.length == 1
#log_debug(" => ", depth: log_depth.to_i) { "convert #{expanded_value.inspect} to list"}
log_debug(" => ", depth: log_depth.to_i) { "convert #{expanded_value.inspect} to list"}
expanded_value = as_array(expanded_value).map do |v|
{'@graph' => as_array(v)}
end
Expand Down
7 changes: 3 additions & 4 deletions lib/json/ld/html/nokogiri.rb
Expand Up @@ -136,11 +136,10 @@ def initialize_html_nokogiri(input, options = {})
input
else
begin
require 'nokogumbo' unless defined?(::Nokogumbo)
input = input.read if input.respond_to?(:read)
::Nokogiri::HTML5(input.dup.force_encoding('utf-8'), max_parse_errors: 1000)
rescue LoadError
::Nokogiri::HTML.parse(input, 'utf-8')
::Nokogiri::HTML5(input.force_encoding('utf-8'), max_parse_errors: 1000)
rescue LoadError, NoMethodError
::Nokogiri::HTML.parse(input, base_uri.to_s, 'utf-8')
end
end

Expand Down
70 changes: 70 additions & 0 deletions spec/compact_spec.rb
Expand Up @@ -954,6 +954,76 @@
}),
processingMode: 'json-ld-1.1'
},
"issue-514": {
input: %({
"http://example.org/ns/prop": [{
"@id": "http://example.org/ns/bar",
"http://example.org/ns/name": "bar"
}, {
"@id": "http://example.org/ns/foo",
"http://example.org/ns/name": "foo"
}]
}),
context: %({
"@context": {
"ex": "http://example.org/ns/",
"prop": {
"@id": "ex:prop",
"@container": "@index",
"@index": "ex:name"
}
}
}),
output: %({
"@context": {
"ex": "http://example.org/ns/",
"prop": {
"@id": "ex:prop",
"@container": "@index",
"@index": "ex:name"
}
},
"prop": {
"foo": { "@id": "ex:foo"},
"bar": { "@id": "ex:bar"}
}
})
},
"issue-514b": {
input: %({
"http://example.org/ns/prop": [{
"@id": "http://example.org/ns/bar",
"http://example.org/ns/name": "bar"
}, {
"@id": "http://example.org/ns/foo",
"http://example.org/ns/name": "foo"
}]
}),
context: %({
"@context": {
"ex": "http://example.org/ns/",
"prop": {
"@id": "ex:prop",
"@container": "@index",
"@index": "http://example.org/ns/name"
}
}
}),
output: %({
"@context": {
"ex": "http://example.org/ns/",
"prop": {
"@id": "ex:prop",
"@container": "@index",
"@index": "http://example.org/ns/name"
}
},
"prop": {
"foo": { "@id": "ex:foo"},
"bar": { "@id": "ex:bar"}
}
})
},
}.each_pair do |title, params|
it(title) {run_compact(params)}
end
Expand Down
9 changes: 8 additions & 1 deletion spec/context_spec.rb
Expand Up @@ -181,7 +181,14 @@ def containers
before {JSON::LD::Context.instance_variable_set(:@cache, nil)}
it "retrieves and parses a remote context document" do
expect(JSON::LD::API).to receive(:documentLoader).with("http://example.com/context", anything).and_yield(remote_doc)
subject.parse(ctx)
ec = subject.parse(ctx)
expect(ec.send(:mappings)).to produce({
"xsd" => "http://www.w3.org/2001/XMLSchema#",
"name" => "http://xmlns.com/foaf/0.1/name",
"homepage" => "http://xmlns.com/foaf/0.1/homepage",
"avatar" => "http://xmlns.com/foaf/0.1/avatar",
"integer" => "http://www.w3.org/2001/XMLSchema#integer"
}, logger)
end
end

Expand Down

0 comments on commit a2c6020

Please sign in to comment.