Skip to content

Commit a1ad43c

Browse files
committed
Finish 2.0.1
2 parents dddc28f + 0670805 commit a1ad43c

26 files changed

+3463
-1046
lines changed

.travis.yml

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,14 @@ script: "bundle exec rspec spec"
44
env:
55
- CI=true
66
rvm:
7-
- 2.0
8-
- 2.1
9-
- 2.2.4
10-
- 2.3.0
11-
- jruby-9.0.4.0
12-
- rbx-2
7+
- 2.2.5
8+
- 2.3.1
9+
- jruby-9.1.2.0
10+
- rbx
1311
cache: bundler
1412
sudo: false
1513
matrix:
1614
allow_failures:
17-
- rvm: rbx-2
18-
- rvm: jruby-9.0.4.0
15+
- rvm: jruby-9.1.2.0
1916

2017

Gemfile

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ gem 'jsonlint', github: "dougbarth/jsonlint", platforms: [:rbx, :m
77

88
group :development do
99
gem 'ebnf', github: "gkellogg/ebnf", branch: "develop"
10-
gem 'sxp', github: "gkellogg/sxp-ruby", branch: "develop"
10+
gem 'sxp', github: "dryruby/sxp.rb", branch: "develop"
1111
gem 'rdf-isomorphic', github: "ruby-rdf/rdf-isomorphic", branch: "develop"
1212
gem 'rdf-turtle', github: "ruby-rdf/rdf-turtle", branch: "develop"
1313
gem 'rdf-trig', github: "ruby-rdf/rdf-trig", branch: "develop"
@@ -20,6 +20,7 @@ group :development, :test do
2020
gem 'simplecov', require: false, platform: :mri
2121
gem 'coveralls', require: false, platform: :mri
2222
gem 'psych', platforms: [:mri, :rbx]
23+
gem 'benchmark-ips'
2324
end
2425

2526
group :debug do
@@ -28,6 +29,10 @@ group :debug do
2829
end
2930

3031
platforms :rbx do
31-
gem 'rubysl', '~> 2.0'
32+
gem 'rubysl', '~> 2.0'
3233
gem 'rubinius', '~> 2.0'
3334
end
35+
36+
platforms :jruby do
37+
gem 'gson', '~> 0.6'
38+
end

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,17 @@ Then, when performing something like expansion:
240240

241241
JSON::LD::API.expand(input, documentLoader: load_document_local)
242242

243+
244+
## Preloading contexts
245+
In many cases, for small documents, processing time can be dominated by loading and parsing remote contexts. In particular, a small schema.org example may need to download a large context and turn it into an internal representation, before the actual document can be expanded for processing. Using {JSON::LD::Context.add_preloaded}, an implementation can perform this loading up-front, and make it available to the processor.
246+
247+
ctx = JSON::LD::Context.new().parse('http://schema.org/')
248+
JSON::LD::Context.add_preloaded('http://schema.org/', ctx)
249+
250+
On lookup, URIs with an `https` prefix are normalized to `http`.
251+
252+
A context may be serialized to Ruby to speed this process using `Context#to_rb`. When loaded, this generated file will add entries to the {JSON::LD::Context::PRELOADED}.
253+
243254
## RDF Reader and Writer
244255
{JSON::LD} also acts as a normal RDF reader and writer, using the standard RDF.rb reader/writer interfaces:
245256

@@ -274,7 +285,7 @@ Note, the API method signatures differed in versions before 1.0, in that they al
274285
* {JSON::LD::Writer}
275286

276287
## Dependencies
277-
* [Ruby](http://ruby-lang.org/) (>= 2.0)
288+
* [Ruby](http://ruby-lang.org/) (>= 2.2.2)
278289
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 2.0)
279290
* [JSON](https://rubygems.org/gems/json) (>= 1.5)
280291

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.0.0.1
1+
2.0.1
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env ruby
2+
require "bundler/setup"
3+
require 'json/ld'
4+
#require File.expand_path('../schema-context', __FILE__)
5+
require 'benchmark/ips'
6+
7+
source = JSON.parse %({
8+
"@context": "http://schema.org/",
9+
"@type": "SoftwareApplication",
10+
"name": "EtherSia",
11+
"description": "IPv6 library for the ENC28J60 Ethernet controller",
12+
"url": "https://github.com/njh/EtherSia",
13+
"author": {
14+
"@type": "Person",
15+
"name": "Nicholas Humfrey <[email protected]>"
16+
},
17+
"applicationCategory": "Communication",
18+
"operatingSystem": "Arduino",
19+
"downloadUrl": "http://downloads.arduino.cc/libraries/njh/EtherSia-1.0.0.zip",
20+
"softwareVersion": "1.0.0",
21+
"fileSize": 77
22+
})
23+
24+
25+
Benchmark.ips do |x|
26+
x.config(time: 10, warmup: 1)
27+
x.report('toRdf') {JSON::LD::API.toRdf(source)}
28+
end

example-files/schema-context.rb

Lines changed: 2121 additions & 0 deletions
Large diffs are not rendered by default.

json-ld.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Gem::Specification.new do |gem|
2525
gem.test_files = Dir.glob('spec/**/*.rb') + Dir.glob('spec/test-files/*')
2626
gem.has_rdoc = false
2727

28-
gem.required_ruby_version = '>= 2.0'
28+
gem.required_ruby_version = '>= 2.2.2'
2929
gem.requirements = []
3030
gem.add_runtime_dependency 'rdf', '~> 2.0'
3131
gem.add_runtime_dependency 'multi_json', '~> 1.11'

lib/json/ld.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..')))
1+
# -*- encoding: utf-8 -*-
2+
# frozen_string_literal: true
3+
$:.unshift(File.expand_path("../ld", __FILE__))
24
require 'rdf' # @see http://rubygems.org/gems/rdf
35
require 'multi_json'
46

lib/json/ld/api.rb

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# -*- encoding: utf-8 -*-
2+
# frozen_string_literal: true
13
require 'openssl'
24
require 'json/ld/expand'
35
require 'json/ld/compact'
@@ -70,12 +72,6 @@ class API
7072
# If set to a value that is not `false`, the JSON-LD processor must modify the output of the Compaction Algorithm or the Expansion Algorithm by coalescing all properties associated with each subject via the Flattening Algorithm. The value of `flatten must` be either an _IRI_ value representing the name of the graph to flatten, or `true`. If the value is `true`, then the first graph encountered in the input document is selected and flattened.
7173
# @option options [String] :processingMode ("json-ld-1.0")
7274
# If set to "json-ld-1.0", the JSON-LD processor must produce exactly the same results as the algorithms defined in this specification. If set to another value, the JSON-LD processor is allowed to extend or modify the algorithms defined in this specification to enable application-specific optimizations. The definition of such optimizations is beyond the scope of this specification and thus not defined. Consequently, different implementations may implement different optimizations. Developers must not define modes beginning with json-ld as they are reserved for future versions of this specification.
73-
# @option options [String] :produceGeneralizedRdf (false)
74-
# Unless the produce generalized RDF flag is set to true, RDF triples containing a blank node predicate are excluded from output.
75-
# @option options [Boolean] :useNativeTypes (false)
76-
# If set to `true`, the JSON-LD processor will use native datatypes for expression xsd:integer, xsd:boolean, and xsd:double values, otherwise, it will use the expanded form.
77-
# @option options [Boolean] :useRdfType (false)
78-
# If set to `true`, the JSON-LD processor will treat `rdf:type` like a normal property instead of using `@type`.
7975
# @option options [Boolean] :rename_bnodes (true)
8076
# Rename bnodes as part of expansion, or keep them the same.
8177
# @option options [Boolean] :unique_bnodes (false)
@@ -141,6 +137,9 @@ def initialize(input, context, options = {}, &block)
141137
end
142138
end
143139
end
140+
141+
# This is used internally only
142+
private :initialize
144143

145144
##
146145
# Expands the given input according to the steps in the Expansion Algorithm. The input must be copied, expanded and returned
@@ -152,6 +151,8 @@ def initialize(input, context, options = {}, &block)
152151
# The JSON-LD object to copy and perform the expansion upon.
153152
# @param [Hash{Symbol => Object}] options
154153
# See options in {JSON::LD::API#initialize}
154+
# @option options [String, #read, Hash, Array, JSON::LD::Context] :expandContext
155+
# A context that is used to initialize the active context when expanding a document.
155156
# @raise [JsonLdError]
156157
# @yield jsonld
157158
# @yieldparam [Array<Hash>] jsonld
@@ -163,7 +164,10 @@ def initialize(input, context, options = {}, &block)
163164
def self.expand(input, options = {})
164165
result = nil
165166
API.new(input, options[:expandContext], options) do |api|
166-
result = api.expand(api.value, nil, api.context)
167+
result = api.expand(api.value, nil, api.context,
168+
ordered: options.fetch(:ordered, true),
169+
framing: options.fetch(:framing, false),
170+
keep_free_floating_nodes: options.fetch(:keep_free_floating_nodes, false))
167171
end
168172

169173
# If, after the algorithm outlined above is run, the resulting element is an
@@ -204,9 +208,9 @@ def self.compact(input, context, options = {})
204208

205209
# 1) Perform the Expansion Algorithm on the JSON-LD input.
206210
# This removes any existing context to allow the given context to be cleanly applied.
207-
expanded = options[:expanded] ? input : API.expand(input, options)
211+
expanded_input = options[:expanded] ? input : API.expand(input, options)
208212

209-
API.new(expanded, context, options) do
213+
API.new(expanded_input, context, options) do
210214
log_debug(".compact") {"expanded input: #{expanded.to_json(JSON_STATE) rescue 'malformed json'}"}
211215
result = compact(value, nil)
212216

@@ -270,7 +274,7 @@ def self.flatten(input, context, options = {})
270274

271275
if context && !flattened.empty?
272276
# 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.
273-
compacted = log_depth {compact(flattened, nil)}
277+
compacted = compact(flattened, nil)
274278
compacted = [compacted] unless compacted.is_a?(Array)
275279
kwgraph = self.context.compact_iri('@graph', quiet: true)
276280
flattened = self.context.serialize.merge(kwgraph => compacted)
@@ -294,7 +298,7 @@ def self.flatten(input, context, options = {})
294298
# @param [Hash{Symbol => Object}] options
295299
# See options in {JSON::LD::API#initialize}
296300
# Other options passed to {JSON::LD::API.expand}
297-
# @option options ['@last', '@always', '@never', '@link'] :embed ('@link')
301+
# @option options ['@last', '@always', '@never', '@link'] :embed ('@last')
298302
# a flag specifying that objects should be directly embedded in the output,
299303
# instead of being referred to by their IRI.
300304
# @option options [Boolean] :explicit (false)
@@ -347,28 +351,25 @@ def self.frame(input, frame, options = {})
347351
expanded_input = options[:expanded] ? input : API.expand(input, options)
348352

349353
# Expand frame to simplify processing
350-
expanded_frame = API.expand(frame, options)
354+
expanded_frame = API.expand(frame, options.merge(framing: true, keep_free_floating_nodes: true))
351355

352356
# Initialize input using frame as context
353357
API.new(expanded_input, nil, options) do
354-
#log_debug(".frame") {"context from frame: #{context.inspect}"}
355358
log_debug(".frame") {"expanded frame: #{expanded_frame.to_json(JSON_STATE) rescue 'malformed json'}"}
356359

357360
# Get framing nodes from expanded input, replacing Blank Node identifiers as necessary
358361
old_logger, @options[:logger] = @options[:logger], []
359-
create_node_map(value, framing_state[:graphs], '@merged')
362+
create_node_map(value, framing_state[:graphs], graph: '@merged')
360363
@options[:logger] = old_logger
361364
framing_state[:subjects] = framing_state[:graphs]['@merged']
362-
log_debug(".frame") {"subjects: #{framing_state[:subjects].to_json(JSON_STATE) rescue 'malformed json'}"}
363365

364366
result = []
365367
frame(framing_state, framing_state[:subjects].keys.sort, (expanded_frame.first || {}), options.merge(parent: result))
366-
log_debug(".frame") {"after frame: #{result.to_json(JSON_STATE) rescue 'malformed json'}"}
367368

368369
# Initalize context from frame
369-
@context = log_depth {@context.parse(frame['@context'])}
370+
@context = @context.parse(frame['@context'])
370371
# Compact result
371-
compacted = log_depth {compact(result, nil)}
372+
compacted = compact(result, nil)
372373
compacted = [compacted] unless compacted.is_a?(Array)
373374

374375
# Add the given context to the output
@@ -449,18 +450,20 @@ def self.toRdf(input, options = {}, &block)
449450
# @param [Array<RDF::Statement>] input
450451
# @param [Hash{Symbol => Object}] options
451452
# See options in {JSON::LD::API#initialize}
453+
# @option options [Boolean] :useRdfType (false)
454+
# If set to `true`, the JSON-LD processor will treat `rdf:type` like a normal property instead of using `@type`.
452455
# @yield jsonld
453456
# @yieldparam [Hash] jsonld
454457
# The JSON-LD document in expanded form
455458
# @yieldreturn [Object] returned object
456459
# @return [Object, Hash]
457460
# If a block is given, the result of evaluating the block is returned, otherwise, the expanded JSON-LD document
458461
def self.fromRdf(input, options = {}, &block)
459-
options = {useNativeTypes: false}.merge!(options)
462+
useRdfType = options.fetch(:useRdfType, false)
460463
result = nil
461464

462465
API.new(nil, nil, options) do |api|
463-
result = api.from_statements(input)
466+
result = api.from_statements(input, useRdfType: useRdfType)
464467
end
465468

466469
block_given? ? yield(result) : result

0 commit comments

Comments
 (0)